From b011edd85d7aefaa00b6d8fe83ca7d8def901149 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 5 Aug 2018 13:12:31 +0200 Subject: [PATCH 001/355] added Overlays container to RulesetContainer this is required for mods such as flashlight which always want to draw objects above hitcircles. If just adding children to a RulesetContainer the hit circles would always be above the added children (no matter the Depth). --- osu.Game/Rulesets/UI/RulesetContainer.cs | 12 ++++++++++++ osu.Game/Screens/Play/Player.cs | 1 + 2 files changed, 13 insertions(+) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index ee34e2df04..27dbc70164 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -69,6 +69,12 @@ namespace osu.Game.Rulesets.UI /// public Playfield Playfield => playfield.Value; + private readonly Container overlays; + /// + /// Place to put drawables above hit objects but below UI. + /// + public Container Overlays => overlays; + /// /// The cursor provided by this . May be null if no cursor is provided. /// @@ -88,6 +94,12 @@ namespace osu.Game.Rulesets.UI { Ruleset = ruleset; playfield = new Lazy(CreatePlayfield); + overlays = new Container + { + RelativeSizeAxes = Axes.Both, + Width = 1, + Height = 1 + }; IsPaused.ValueChanged += paused => { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2e23bb16f0..31c3e06705 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -178,6 +178,7 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Child = RulesetContainer }, + RulesetContainer.Overlays, new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, From b33954d9db69ec37ec6f70ec4c8dca60420df957 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 5 Aug 2018 14:20:56 +0200 Subject: [PATCH 002/355] Implement blinds mod --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 29 ++++++ .../Objects/Drawables/DrawableOsuBlinds.cs | 96 +++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- osu.Game/Rulesets/Mods/ModBlinds.cs | 24 +++++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs create mode 100644 osu.Game/Rulesets/Mods/ModBlinds.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs new file mode 100644 index 0000000000..cefaf02a17 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.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 osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModBlinds : ModBlinds + { + public override double ScoreMultiplier => 1.12; + private DrawableOsuBlinds flashlight; + + public override void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + { + rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(restrictTo: rulesetContainer.Playfield)); + } + + public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + scoreProcessor.Health.ValueChanged += val => { + flashlight.Value = (float)val; + }; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs new file mode 100644 index 0000000000..ced5947ba6 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -0,0 +1,96 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using OpenTK.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables +{ + /// + /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. + /// + public class DrawableOsuBlinds : Container + { + private Box box1, box2; + private float target = 1; + private readonly float easing = 1; + private readonly Container restrictTo; + + /// + /// + /// Percentage of playfield to extend blinds over. Basically moves the origin points where the blinds start. + /// + /// + /// -1 would mean the blinds always cover the whole screen no matter health. + /// 0 would mean the blinds will only ever be on the edge of the playfield on 0% health. + /// 1 would mean the blinds are fully outside the playfield on 50% health. + /// Infinity would mean the blinds are always outside the playfield except on 100% health. + /// + /// + private const float leniency = 0.2f; + + public DrawableOsuBlinds(Container restrictTo) + { + this.restrictTo = restrictTo; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + Width = 1; + Height = 1; + + Add(box1 = new Box + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Y, + Width = 0, + Height = 1 + }); + Add(box2 = new Box + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Y, + Width = 0, + Height = 1 + }); + } + + protected override void Update() + { + float start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; + float end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; + float rawWidth = end - start; + start -= rawWidth * leniency * 0.5f; + end += rawWidth * leniency * 0.5f; + float width = (end - start) * 0.5f * easing; + // different values in case the playfield ever moves from center to somewhere else. + box1.Width = start + width; + box2.Width = DrawWidth - end + width; + } + + /// + /// Health between 0 and 1 for the blinds to base the width on. Will get animated for 200ms using out-quintic easing. + /// + public float Value + { + set + { + target = value; + this.TransformTo(nameof(easing), target, 200, Easing.OutQuint); + } + get + { + return target; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index fa6e9a018a..294078b0f3 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()), new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), new OsuModHidden(), - new OsuModFlashlight(), + new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), }; case ModType.Conversion: return new Mod[] diff --git a/osu.Game/Rulesets/Mods/ModBlinds.cs b/osu.Game/Rulesets/Mods/ModBlinds.cs new file mode 100644 index 0000000000..1494b314c2 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModBlinds.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModBlinds : Mod, IApplicableToRulesetContainer, IApplicableToScoreProcessor + where T : HitObject + { + public override string Name => "Blinds"; + public override string ShortenedName => "BL"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_flashlight; + public override ModType Type => ModType.DifficultyIncrease; + public override string Description => "Play with blinds on your screen."; + public override bool Ranked => false; + + public abstract void ApplyToRulesetContainer(RulesetContainer rulesetContainer); + public abstract void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); + } +} From 5f3c0549c99b17b9441b09df4f545b7ed3f029cf Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sat, 15 Sep 2018 23:44:22 +0200 Subject: [PATCH 003/355] Sprites in blinds mod & gameplay improvements There are now skinnable actual blinds (shoji screen panels) The black overlay is still behind them to avoid cheating with skins The blinds don't open linearly anymore, they are health squared now When easy mod is on, there is always a little gap open --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 +- .../Objects/Drawables/DrawableOsuBlinds.cs | 74 ++++++++++++++++++- .../Drawables/Pieces/ModBlindsPanelSprite.cs | 26 +++++++ osu.Game/Rulesets/UI/RulesetContainer.cs | 2 + 4 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index cefaf02a17..a4441a2bdc 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using System.Linq; namespace osu.Game.Rulesets.Osu.Mods { @@ -16,7 +17,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(restrictTo: rulesetContainer.Playfield)); + bool hasEasy = rulesetContainer.ActiveMods.Count(mod => mod is ModEasy) > 0; + rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(restrictTo: rulesetContainer.Playfield, hasEasy: hasEasy)); } public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index ced5947ba6..69fc4a1d57 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -6,6 +6,10 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Game.Skinning; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -14,10 +18,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// public class DrawableOsuBlinds : Container { + /// + /// Black background boxes behind blind panel textures. + /// private Box box1, box2; + private Sprite panelLeft, panelRight; + private Sprite bgPanelLeft, bgPanelRight; + private ISkinSource skin; + private float target = 1; private readonly float easing = 1; + private readonly Container restrictTo; + private readonly bool hasEasy; /// /// @@ -30,15 +43,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// Infinity would mean the blinds are always outside the playfield except on 100% health. /// /// - private const float leniency = 0.2f; + private const float leniency = 0.1f; - public DrawableOsuBlinds(Container restrictTo) + /// + /// Multiplier for adding a gap when the Easy mod is also currently applied. + /// + private const float easy_position_multiplier = 0.95f; + + public DrawableOsuBlinds(Container restrictTo, bool hasEasy) { this.restrictTo = restrictTo; + this.hasEasy = hasEasy; } [BackgroundDependencyLoader] - private void load() + private void load(ISkinSource skin, TextureStore textures) { RelativeSizeAxes = Axes.Both; Width = 1; @@ -62,6 +81,36 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Width = 0, Height = 1 }); + + Add(bgPanelLeft = new ModBlindsPanelSprite { + Origin = Anchor.TopRight, + Colour = Color4.Gray + }); + Add(bgPanelRight = new ModBlindsPanelSprite { + Origin = Anchor.TopLeft, + Colour = Color4.Gray + }); + + Add(panelLeft = new ModBlindsPanelSprite { + Origin = Anchor.TopRight + }); + Add(panelRight = new ModBlindsPanelSprite { + Origin = Anchor.TopLeft + }); + + this.skin = skin; + skin.SourceChanged += skinChanged; + PanelTexture = textures.Get("Play/osu/blinds-panel"); + } + + private void skinChanged() + { + PanelTexture = skin.GetTexture("Play/osu/blinds-panel"); + } + + private static float applyAdjustmentCurve(float value) + { + return value * value; } protected override void Update() @@ -71,10 +120,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables float rawWidth = end - start; start -= rawWidth * leniency * 0.5f; end += rawWidth * leniency * 0.5f; - float width = (end - start) * 0.5f * easing; + + float width = (end - start) * 0.5f * applyAdjustmentCurve((hasEasy ? easy_position_multiplier : 1) * easing); // different values in case the playfield ever moves from center to somewhere else. box1.Width = start + width; box2.Width = DrawWidth - end + width; + + panelLeft.X = start + width; + panelRight.X = end - width; + bgPanelLeft.X = start; + bgPanelRight.X = end; } /// @@ -92,5 +147,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return target; } } + + public Texture PanelTexture + { + set + { + panelLeft.Texture = value; + panelRight.Texture = value; + bgPanelLeft.Texture = value; + bgPanelRight.Texture = value; + } + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs new file mode 100644 index 0000000000..459ea920fa --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces +{ + public class ModBlindsPanelSprite : Sprite + { + public ModBlindsPanelSprite() + { + RelativeSizeAxes = Axes.None; + Anchor = Anchor.TopLeft; + } + + protected override void Update() + { + Height = Parent?.DrawHeight ?? 0; + if (Height == 0 || Texture is null) + Width = 0; + else + Width = Texture.Width / (float)Texture.Height * Height; + } + } +} diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 02ec17e969..7b146f5b84 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -328,6 +328,8 @@ namespace osu.Game.Rulesets.UI Playfield.Size = GetAspectAdjustedSize() * PlayfieldArea; } + public IEnumerable ActiveMods { get => Mods; } + /// /// Computes the size of the in relative coordinate space after aspect adjustments. /// From 91b25870ef382039b7479ebdf3b4d4532c504701 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 16 Sep 2018 12:48:36 +0200 Subject: [PATCH 004/355] Make fruit catcher enter and leave what's behind the blinds --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 17 +- .../Objects/Drawables/DrawableOsuBlinds.cs | 164 ++++++++++++++++-- 2 files changed, 164 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index a4441a2bdc..45c22b7153 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using System.Linq; namespace osu.Game.Rulesets.Osu.Mods { @@ -17,8 +16,16 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - bool hasEasy = rulesetContainer.ActiveMods.Count(mod => mod is ModEasy) > 0; - rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(restrictTo: rulesetContainer.Playfield, hasEasy: hasEasy)); + bool hasEasy = false; + bool hasHardrock = false; + foreach (var mod in rulesetContainer.ActiveMods) + { + if (mod is ModEasy) + hasEasy = true; + if (mod is ModHardRock) + hasHardrock = true; + } + rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(restrictTo: rulesetContainer.Playfield, hasEasy: hasEasy, hasHardrock: hasHardrock)); } public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -26,6 +33,10 @@ namespace osu.Game.Rulesets.Osu.Mods scoreProcessor.Health.ValueChanged += val => { flashlight.Value = (float)val; }; + scoreProcessor.Combo.ValueChanged += val => { + if (val > 0 && val % 30 == 0) + flashlight.TriggerNPC(); + }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index 69fc4a1d57..7c539e0e94 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -10,6 +10,7 @@ using osu.Game.Skinning; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using System; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -24,13 +25,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Box box1, box2; private Sprite panelLeft, panelRight; private Sprite bgPanelLeft, bgPanelRight; + + private Drawable bgRandomNpc; + private Drawable randomNpc; + private const float npc_movement_start = 1.5f; + private float npcPosition = npc_movement_start; + private bool animatingNPC; + private Random random; + private ISkinSource skin; + private float targetClamp = 1; private float target = 1; private readonly float easing = 1; + private const float black_depth = 10; + private const float bg_panel_depth = 8; + private const float fg_panel_depth = 4; + private const float npc_depth = 6; + private readonly Container restrictTo; - private readonly bool hasEasy; + private readonly bool modEasy, modHardrock; /// /// @@ -50,10 +65,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// private const float easy_position_multiplier = 0.95f; - public DrawableOsuBlinds(Container restrictTo, bool hasEasy) + public DrawableOsuBlinds(Container restrictTo, bool hasEasy, bool hasHardrock) { this.restrictTo = restrictTo; - this.hasEasy = hasEasy; + + modEasy = hasEasy; + modHardrock = hasHardrock; } [BackgroundDependencyLoader] @@ -70,7 +87,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Colour = Color4.Black, RelativeSizeAxes = Axes.Y, Width = 0, - Height = 1 + Height = 1, + Depth = black_depth }); Add(box2 = new Box { @@ -79,23 +97,56 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Colour = Color4.Black, RelativeSizeAxes = Axes.Y, Width = 0, - Height = 1 + Height = 1, + Depth = black_depth }); Add(bgPanelLeft = new ModBlindsPanelSprite { Origin = Anchor.TopRight, - Colour = Color4.Gray + Colour = Color4.Gray, + Depth = bg_panel_depth + 1 }); - Add(bgPanelRight = new ModBlindsPanelSprite { - Origin = Anchor.TopLeft, - Colour = Color4.Gray + Add(panelLeft = new ModBlindsPanelSprite { + Origin = Anchor.TopRight, + Depth = bg_panel_depth }); - Add(panelLeft = new ModBlindsPanelSprite { - Origin = Anchor.TopRight + Add(bgPanelRight = new ModBlindsPanelSprite { + Origin = Anchor.TopLeft, + Colour = Color4.Gray, + Depth = fg_panel_depth + 1 }); Add(panelRight = new ModBlindsPanelSprite { - Origin = Anchor.TopLeft + Origin = Anchor.TopLeft, + Depth = fg_panel_depth + }); + + + random = new Random(); + Add(bgRandomNpc = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.Black, + Width = 512 * 0.4f, + Height = 512 * 0.95f, + RelativePositionAxes = Axes.Y, + X = -512, + Y = 0, + Depth = black_depth + }); + Add(new SkinnableDrawable("Play/Catch/fruit-catcher-idle", name => randomNpc = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Texture = textures.Get(name), + Width = 512, + Height = 512, + RelativePositionAxes = Axes.Y, + X = -512, + Y = 0 + }) { + Depth = npc_depth }); this.skin = skin; @@ -108,9 +159,36 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables PanelTexture = skin.GetTexture("Play/osu/blinds-panel"); } + private float applyGap(float value) + { + float ret; + if (modEasy) + { + float multiplier = 0.95f; + ret = value * multiplier; + } + else if (modHardrock) + { + float multiplier = 1.1f; + ret = value * multiplier; + } + else + { + ret = value; + } + + if (ret > targetClamp) + return targetClamp; + else if (ret < 0) + return 0; + else + return ret; + } + private static float applyAdjustmentCurve(float value) { - return value * value; + // lagrange polinominal for (0,0) (0.5,0.35) (1,1) should make a good curve + return 0.6f * value * value + 0.4f * value; } protected override void Update() @@ -121,7 +199,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables start -= rawWidth * leniency * 0.5f; end += rawWidth * leniency * 0.5f; - float width = (end - start) * 0.5f * applyAdjustmentCurve((hasEasy ? easy_position_multiplier : 1) * easing); + float width = (end - start) * 0.5f * applyAdjustmentCurve(applyGap(easing)); // different values in case the playfield ever moves from center to somewhere else. box1.Width = start + width; box2.Width = DrawWidth - end + width; @@ -130,6 +208,64 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables panelRight.X = end - width; bgPanelLeft.X = start; bgPanelRight.X = end; + + float adjustedNpcPosition = npcPosition * rawWidth; + if (randomNpc != null) + randomNpc.X = adjustedNpcPosition; + bgRandomNpc.X = adjustedNpcPosition; + } + + public void TriggerNPC() + { + if (animatingNPC) + return; + + bool left = (random.Next() & 1) != 0; + bool exit = (random.Next() & 1) != 0; + float start, end; + + if (left) + { + start = -npc_movement_start; + end = npc_movement_start; + + randomNpc.Scale = new OpenTK.Vector2(1, 1); + } + else + { + start = npc_movement_start; + end = -npc_movement_start; + + randomNpc.Scale = new OpenTK.Vector2(-1, 1); + } + + // depths for exit from the left and entry from the right + if (left == exit) + { + ChangeChildDepth(bgPanelLeft, fg_panel_depth + 1); + ChangeChildDepth(panelLeft, fg_panel_depth); + + ChangeChildDepth(bgPanelRight, bg_panel_depth + 1); + ChangeChildDepth(panelRight, bg_panel_depth); + } + else // depths for entry from the left or exit from the right + { + ChangeChildDepth(bgPanelLeft, bg_panel_depth + 1); + ChangeChildDepth(panelLeft, bg_panel_depth); + + ChangeChildDepth(bgPanelRight, fg_panel_depth + 1); + ChangeChildDepth(panelRight, fg_panel_depth); + } + + animatingNPC = true; + npcPosition = start; + this.TransformTo(nameof(npcPosition), end, 3000, Easing.OutSine).Finally(_ => animatingNPC = false); + + targetClamp = 1; + this.Delay(600).TransformTo(nameof(targetClamp), 0.6f, 300).Delay(500).TransformTo(nameof(targetClamp), 1f, 300); + + randomNpc?.FadeIn(250).Delay(2000).FadeOut(500); + bgRandomNpc.FadeIn(250).Delay(2000).FadeOut(500); } /// From 633e8fafee41ada907889bd43f725ad08f95c25b Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 16 Sep 2018 12:57:54 +0200 Subject: [PATCH 005/355] Style & const fix --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- .../Objects/Drawables/DrawableOsuBlinds.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 45c22b7153..9639dd5dd8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; scoreProcessor.Combo.ValueChanged += val => { if (val > 0 && val % 30 == 0) - flashlight.TriggerNPC(); + flashlight.TriggerNpc(); }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index 7c539e0e94..8c2a569e92 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Drawable randomNpc; private const float npc_movement_start = 1.5f; private float npcPosition = npc_movement_start; - private bool animatingNPC; + private bool animatingNpc; private Random random; private ISkinSource skin; @@ -164,12 +164,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables float ret; if (modEasy) { - float multiplier = 0.95f; + const float multiplier = 0.95f; ret = value * multiplier; } else if (modHardrock) { - float multiplier = 1.1f; + const float multiplier = 1.1f; ret = value * multiplier; } else @@ -215,9 +215,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables bgRandomNpc.X = adjustedNpcPosition; } - public void TriggerNPC() + public void TriggerNpc() { - if (animatingNPC) + if (animatingNpc) return; bool left = (random.Next() & 1) != 0; @@ -257,9 +257,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ChangeChildDepth(panelRight, fg_panel_depth); } - animatingNPC = true; + animatingNpc = true; npcPosition = start; - this.TransformTo(nameof(npcPosition), end, 3000, Easing.OutSine).Finally(_ => animatingNPC = false); + this.TransformTo(nameof(npcPosition), end, 3000, Easing.OutSine).Finally(_ => animatingNpc = false); targetClamp = 1; this.Delay(600).TransformTo(nameof(targetClamp), 0.6f, 300).Delay(500).TransformTo(nameof(targetClamp), 1f, 300); From c9ea5ce817fac5d860fefef7d2cf1fd7be459463 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 16 Sep 2018 16:51:18 +0200 Subject: [PATCH 006/355] Made blinds open during breaks and start --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- .../Objects/Drawables/DrawableOsuBlinds.cs | 89 ++++++++++++------- .../Drawables/Pieces/ModBlindsPanelSprite.cs | 2 +- osu.Game/Rulesets/Mods/ModBlinds.cs | 2 +- 4 files changed, 62 insertions(+), 33 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 9639dd5dd8..4baea5d0c0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods if (mod is ModHardRock) hasHardrock = true; } - rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(restrictTo: rulesetContainer.Playfield, hasEasy: hasEasy, hasHardrock: hasHardrock)); + rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(rulesetContainer.Playfield, hasEasy, hasHardrock, rulesetContainer.Beatmap)); } public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index 8c2a569e92..ae099cd589 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using System; +using osu.Game.Beatmaps; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// /// Black background boxes behind blind panel textures. /// - private Box box1, box2; + private Box blackBoxLeft, blackBoxRight; private Sprite panelLeft, panelRight; private Sprite bgPanelLeft, bgPanelRight; @@ -30,12 +31,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Drawable randomNpc; private const float npc_movement_start = 1.5f; private float npcPosition = npc_movement_start; - private bool animatingNpc; + private bool animatingBlinds; + private Beatmap beatmap; private Random random; private ISkinSource skin; private float targetClamp = 1; + private float targetBreakMultiplier = 0; private float target = 1; private readonly float easing = 1; @@ -60,14 +63,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// private const float leniency = 0.1f; - /// - /// Multiplier for adding a gap when the Easy mod is also currently applied. - /// - private const float easy_position_multiplier = 0.95f; - - public DrawableOsuBlinds(Container restrictTo, bool hasEasy, bool hasHardrock) + public DrawableOsuBlinds(Container restrictTo, bool hasEasy, bool hasHardrock, Beatmap beatmap) { this.restrictTo = restrictTo; + this.beatmap = beatmap; modEasy = hasEasy; modHardrock = hasHardrock; @@ -80,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Width = 1; Height = 1; - Add(box1 = new Box + Add(blackBoxLeft = new Box { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, @@ -90,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Height = 1, Depth = black_depth }); - Add(box2 = new Box + Add(blackBoxRight = new Box { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -161,28 +160,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private float applyGap(float value) { - float ret; + const float easy_multiplier = 0.95f; + const float hardrock_multiplier = 1.1f; + + float multiplier = 1; if (modEasy) { - const float multiplier = 0.95f; - ret = value * multiplier; + multiplier = easy_multiplier; + // TODO: include OD/CS } else if (modHardrock) { - const float multiplier = 1.1f; - ret = value * multiplier; - } - else - { - ret = value; + multiplier = hardrock_multiplier; + // TODO: include OD/CS } - if (ret > targetClamp) - return targetClamp; - else if (ret < 0) - return 0; - else - return ret; + return OpenTK.MathHelper.Clamp(value * multiplier, 0, targetClamp) * targetBreakMultiplier; } private static float applyAdjustmentCurve(float value) @@ -201,8 +194,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables float width = (end - start) * 0.5f * applyAdjustmentCurve(applyGap(easing)); // different values in case the playfield ever moves from center to somewhere else. - box1.Width = start + width; - box2.Width = DrawWidth - end + width; + blackBoxLeft.Width = start + width; + blackBoxRight.Width = DrawWidth - end + width; panelLeft.X = start + width; panelRight.X = end - width; @@ -215,9 +208,45 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables bgRandomNpc.X = adjustedNpcPosition; } + protected override void LoadComplete() + { + const float break_open_early = 500; + + base.LoadComplete(); + + var firstObj = beatmap.HitObjects[0]; + var startDelay = firstObj.StartTime - firstObj.TimePreempt - firstObj.TimeFadeIn; + + using (BeginAbsoluteSequence(startDelay, true)) + LeaveBreak(); + + foreach (var breakInfo in beatmap.Breaks) + { + if (breakInfo.HasEffect) + { + using (BeginAbsoluteSequence(breakInfo.StartTime - break_open_early, true)) + { + EnterBreak(); + using (BeginDelayedSequence(breakInfo.Duration + break_open_early, true)) + LeaveBreak(); + } + } + } + } + + public void EnterBreak() + { + this.TransformTo(nameof(targetBreakMultiplier), 0f, 1000, Easing.OutSine); + } + + public void LeaveBreak() + { + this.TransformTo(nameof(targetBreakMultiplier), 1f, 2500, Easing.OutBounce); + } + public void TriggerNpc() { - if (animatingNpc) + if (animatingBlinds) return; bool left = (random.Next() & 1) != 0; @@ -257,9 +286,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ChangeChildDepth(panelRight, fg_panel_depth); } - animatingNpc = true; + animatingBlinds = true; npcPosition = start; - this.TransformTo(nameof(npcPosition), end, 3000, Easing.OutSine).Finally(_ => animatingNpc = false); + this.TransformTo(nameof(npcPosition), end, 3000, Easing.OutSine).Finally(_ => animatingBlinds = false); targetClamp = 1; this.Delay(600).TransformTo(nameof(targetClamp), 0.6f, 300).Delay(500).TransformTo(nameof(targetClamp), 1f, 300); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs index 459ea920fa..c6e2db1842 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void Update() { Height = Parent?.DrawHeight ?? 0; - if (Height == 0 || Texture is null) + if (Height == 0 || Texture == null) Width = 0; else Width = Texture.Width / (float)Texture.Height * Height; diff --git a/osu.Game/Rulesets/Mods/ModBlinds.cs b/osu.Game/Rulesets/Mods/ModBlinds.cs index 1494b314c2..bf68300cd6 100644 --- a/osu.Game/Rulesets/Mods/ModBlinds.cs +++ b/osu.Game/Rulesets/Mods/ModBlinds.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mods { public override string Name => "Blinds"; public override string ShortenedName => "BL"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_flashlight; + public override FontAwesome Icon => FontAwesome.fa_adjust; public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Play with blinds on your screen."; public override bool Ranked => false; From 2de3b33780ac0871188be90a29a703475f7576de Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 16 Sep 2018 16:57:43 +0200 Subject: [PATCH 007/355] Readonly fixes --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index ae099cd589..4fe5b4e4fb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -32,13 +32,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private const float npc_movement_start = 1.5f; private float npcPosition = npc_movement_start; private bool animatingBlinds; - private Beatmap beatmap; + + private readonly Beatmap beatmap; private Random random; private ISkinSource skin; private float targetClamp = 1; - private float targetBreakMultiplier = 0; + private readonly float targetBreakMultiplier = 0; private float target = 1; private readonly float easing = 1; From 8a01fc1bffa8c323da188aaa50a19c446ce2f61b Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Mon, 17 Sep 2018 20:31:50 +0200 Subject: [PATCH 008/355] Make random in blinds mod the same every replay --- .../Objects/Drawables/DrawableOsuBlinds.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index 4fe5b4e4fb..15d394dbb4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -121,8 +121,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Depth = fg_panel_depth }); - - random = new Random(); + // seed with unique seed per map so NPC always comes from the same sides for a same map for reproducible replays. + random = new Random(beatmap.Metadata.ToString().GetHashCode()); Add(bgRandomNpc = new Box { Anchor = Anchor.Centre, @@ -133,7 +133,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables RelativePositionAxes = Axes.Y, X = -512, Y = 0, - Depth = black_depth + Depth = black_depth, + Alpha = 0 }); Add(new SkinnableDrawable("Play/Catch/fruit-catcher-idle", name => randomNpc = new Sprite { @@ -144,7 +145,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Height = 512, RelativePositionAxes = Axes.Y, X = -512, - Y = 0 + Y = 0, + Alpha = 0 }) { Depth = npc_depth }); From 72e82b660d91eeae22a9d0d5acc8d25f274a8cf2 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Sun, 28 Oct 2018 01:14:16 +0200 Subject: [PATCH 009/355] Adjust blinds animations based on player feedback --- .../Objects/Drawables/DrawableOsuBlinds.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index 1ba18dacbc..2bbd31fc46 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -214,13 +214,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void LoadComplete() { const float break_open_early = 500; + const float break_close_late = 250; base.LoadComplete(); var firstObj = beatmap.HitObjects[0]; - var startDelay = firstObj.StartTime - firstObj.TimePreempt - firstObj.TimeFadeIn; + var startDelay = firstObj.StartTime - firstObj.TimePreempt; - using (BeginAbsoluteSequence(startDelay, true)) + using (BeginAbsoluteSequence(startDelay + break_close_late, true)) LeaveBreak(); foreach (var breakInfo in beatmap.Breaks) @@ -230,7 +231,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables using (BeginAbsoluteSequence(breakInfo.StartTime - break_open_early, true)) { EnterBreak(); - using (BeginDelayedSequence(breakInfo.Duration + break_open_early, true)) + using (BeginDelayedSequence(breakInfo.Duration + break_open_early + break_close_late, true)) LeaveBreak(); } } From 36b458bdee3dedaee369a05222d22631b6212cb0 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 08:56:19 +0700 Subject: [PATCH 010/355] Fixed #3777 --- .../Judgements/TaikoDrumRollJudgement.cs | 11 ++++++++++ .../Objects/Drawables/DrawableHit.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 4 ++++ .../Scoring/TaikoScoreProcessor.cs | 22 ++++++++++++++++++- 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs new file mode 100644 index 0000000000..b1ac49b939 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -0,0 +1,11 @@ +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Judgements +{ + class TaikoDrumRollJudgement : TaikoJudgement + { + public override bool AffectsCombo => false; + + protected override int NumericResultFor(HitResult result) => 0; + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 6f7264e23b..a1681b38f1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = HitResult.Miss); return; } - + if (!userTriggered) { if (timeOffset > second_hit_window) @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } if (Math.Abs(MainObject.Result.TimeOffset - timeOffset) < second_hit_window) - ApplyResult(r => r.Type = HitResult.Great); + ApplyResult(r => r.Type = MainObject.Result.Type); } public override bool OnPressed(TaikoAction action) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 405ea85f0d..0dc460643a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -5,11 +5,15 @@ using osu.Game.Rulesets.Objects.Types; using System; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { public class DrumRoll : TaikoHitObject, IHasEndTime { + public override Judgement CreateJudgement() => new TaikoDrumRollJudgement(); + /// /// Drum roll distance that results in a duration of 1 speed-adjusted beat length. /// diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index cf33141027..cf974a6223 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -80,7 +80,27 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyResult(result); - bool isTick = result.Judgement is TaikoDrumRollTickJudgement; + bool isTick = false; + bool isRoll = false; + bool isStrong = false; + + isTick = result.Judgement is TaikoDrumRollTickJudgement; + if (!isTick) + { + isRoll = result.Judgement is TaikoDrumRollJudgement; + if (!isRoll) + { + isStrong = result.Judgement is TaikoStrongJudgement; + } + } + + //Don't change HP based on drum roll fullness for compatibility + if (isRoll) + return; + + //If the object is strong, HP change is already handled in MainObject + if (isStrong) + return; // Apply HP changes switch (result.Type) From 17337e05a1f857ebc583f8aa589f9cdac90b411e Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 09:06:40 +0700 Subject: [PATCH 011/355] Fixed whitespace --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index a1681b38f1..48731388cb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = HitResult.Miss); return; } - + if (!userTriggered) { if (timeOffset > second_hit_window) From 00a243f7f26e77e5987e8b798419f1fe0d4323ef Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 09:19:41 +0700 Subject: [PATCH 012/355] Add license header --- .../Judgements/TaikoDrumRollJudgement.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index b1ac49b939..48ccdb30e1 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -1,11 +1,14 @@ -using osu.Game.Rulesets.Scoring; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements { class TaikoDrumRollJudgement : TaikoJudgement { public override bool AffectsCombo => false; - + protected override int NumericResultFor(HitResult result) => 0; } } From ce1e6d93e47947e85487395d076b7754b604713c Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 09:45:57 +0700 Subject: [PATCH 013/355] Update TaikoScoreProcessor.cs --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index cf974a6223..a2a0251860 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -80,11 +80,10 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyResult(result); - bool isTick = false; bool isRoll = false; bool isStrong = false; + bool isTick = result.Judgement is TaikoDrumRollTickJudgement; - isTick = result.Judgement is TaikoDrumRollTickJudgement; if (!isTick) { isRoll = result.Judgement is TaikoDrumRollJudgement; From a378c5054428d00f0300d09ad2c92813f0a0dd90 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 09:47:12 +0700 Subject: [PATCH 014/355] Fix TaikoDrumRollJudgement visibilityy --- osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 48ccdb30e1..8ef98c6dac 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -5,7 +5,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements { - class TaikoDrumRollJudgement : TaikoJudgement + public class TaikoDrumRollJudgement : TaikoJudgement { public override bool AffectsCombo => false; From 2ca9864301f1676ce36041d4b27ca6c90bcfe9a6 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 22:05:13 +0700 Subject: [PATCH 015/355] Fixed taiko swell hp and scoring --- .../Judgements/TaikoDrumRollJudgement.cs | 2 ++ .../TaikoIntermediateSwellJudgement.cs | 21 ------------- .../Judgements/TaikoJudgement.cs | 5 ++++ .../Judgements/TaikoStrongJudgement.cs | 3 ++ .../Judgements/TaikoSwellJudgement.cs | 14 +++++++++ .../Judgements/TaikoSwellTickJudgement.cs | 25 ++++++++++++++++ .../Objects/Drawables/DrawableSwellTick.cs | 4 +-- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 4 +++ osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 4 +++ .../Scoring/TaikoScoreProcessor.cs | 30 +++++++------------ 10 files changed, 69 insertions(+), 43 deletions(-) delete mode 100644 osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs create mode 100644 osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs create mode 100644 osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 8ef98c6dac..4663d00bdc 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -9,6 +9,8 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; + public override bool AffectsHP => false; + protected override int NumericResultFor(HitResult result) => 0; } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs deleted file mode 100644 index 81a1bd1344..0000000000 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Taiko.Judgements -{ - public class TaikoIntermediateSwellJudgement : TaikoJudgement - { - public override HitResult MaxResult => HitResult.Great; - - public override bool AffectsCombo => false; - - /// - /// Computes the numeric result value for the combo portion of the score. - /// - /// The result to compute the value for. - /// The numeric result value. - protected override int NumericResultFor(HitResult result) => 0; - } -} diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 9b1f7a08b5..386495bf1b 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -10,6 +10,11 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override HitResult MaxResult => HitResult.Great; + /// + /// Whether this should affect user's hitpoints. + /// + public virtual bool AffectsHP => true; + /// /// Computes the numeric result value for the combo portion of the score. /// diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index ccfdeb5b0e..2665540d07 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -5,6 +5,9 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoStrongJudgement : TaikoJudgement { + // MainObject already changes the HP + public override bool AffectsHP => false; + public override bool AffectsCombo => false; } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs new file mode 100644 index 0000000000..b913f5d730 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Judgements +{ + public class TaikoSwellJudgement : TaikoJudgement + { + public override bool AffectsCombo => false; + + protected override int NumericResultFor(HitResult result) => 0; + } +} diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs new file mode 100644 index 0000000000..8dd03796ea --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.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 osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Judgements +{ + public class TaikoSwellTickJudgement : TaikoJudgement + { + public override bool AffectsCombo => false; + + public override bool AffectsHP => false; + + protected override int NumericResultFor(HitResult result) + { + switch (result) + { + default: + return 0; + case HitResult.Great: + return 300; + } + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 36c468c6d6..0a73474cf3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -6,11 +6,11 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public class DrawableSwellTick : DrawableTaikoHitObject + public class DrawableSwellTick : DrawableTaikoHitObject { public override bool DisplayResult => false; - public DrawableSwellTick(TaikoHitObject hitObject) + public DrawableSwellTick(SwellTick hitObject) : base(hitObject) { } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 702bf63bf5..67e2cae5eb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -3,11 +3,15 @@ using System; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { public class Swell : TaikoHitObject, IHasEndTime { + public override Judgement CreateJudgement() => new TaikoSwellJudgement(); + public double EndTime => StartTime + Duration; public double Duration { get; set; } diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 49eb6d2a15..38f77fa1e7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -1,9 +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.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; + namespace osu.Game.Rulesets.Taiko.Objects { public class SwellTick : TaikoHitObject { + public override Judgement CreateJudgement() => new TaikoSwellTickJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index a2a0251860..06d207695f 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -79,27 +79,15 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override void ApplyResult(JudgementResult result) { base.ApplyResult(result); + + if (!((TaikoJudgement)result.Judgement).AffectsHP) + return; - bool isRoll = false; - bool isStrong = false; + bool isSwell = false; bool isTick = result.Judgement is TaikoDrumRollTickJudgement; - if (!isTick) - { - isRoll = result.Judgement is TaikoDrumRollJudgement; - if (!isRoll) - { - isStrong = result.Judgement is TaikoStrongJudgement; - } - } - - //Don't change HP based on drum roll fullness for compatibility - if (isRoll) - return; - - //If the object is strong, HP change is already handled in MainObject - if (isStrong) - return; + if(!isTick) + isSwell = result.Judgement is TaikoSwellJudgement; // Apply HP changes switch (result.Type) @@ -110,12 +98,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring Health.Value += hpIncreaseMiss; break; case HitResult.Good: - Health.Value += hpIncreaseGood; + // Swells shouldn't increase HP + if (!isSwell) + Health.Value += hpIncreaseGood; break; case HitResult.Great: if (isTick) Health.Value += hpIncreaseTick; - else + else if(!isSwell) Health.Value += hpIncreaseGreat; break; } From d30ab4f77cdc7a6b0e105438733dde02b0e1a613 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 22:12:01 +0700 Subject: [PATCH 016/355] fixed whitespace --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 06d207695f..7569edbdb7 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override void ApplyResult(JudgementResult result) { base.ApplyResult(result); - + if (!((TaikoJudgement)result.Judgement).AffectsHP) return; From 13a166a6453714251c920513748cf88440627dc1 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 22:26:23 +0700 Subject: [PATCH 017/355] rename TaikoJudgement.AffectsHP to AffectsHp --- osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 4663d00bdc..ca81b13053 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - public override bool AffectsHP => false; + public override bool AffectsHp => false; protected override int NumericResultFor(HitResult result) => 0; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 386495bf1b..f4dd90e93b 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements /// /// Whether this should affect user's hitpoints. /// - public virtual bool AffectsHP => true; + public virtual bool AffectsHp => true; /// /// Computes the numeric result value for the combo portion of the score. diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index 2665540d07..67b113e795 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -6,7 +6,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoStrongJudgement : TaikoJudgement { // MainObject already changes the HP - public override bool AffectsHP => false; + public override bool AffectsHp => false; public override bool AffectsCombo => false; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs index 8dd03796ea..8a9a023c22 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - public override bool AffectsHP => false; + public override bool AffectsHp => false; protected override int NumericResultFor(HitResult result) { diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 7569edbdb7..064a7d519b 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyResult(result); - if (!((TaikoJudgement)result.Judgement).AffectsHP) + if (!((TaikoJudgement)result.Judgement).AffectsHp) return; bool isSwell = false; From 4184f1770939fe303d43ad2aa8a1f4d73744e986 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 29 Nov 2018 23:12:02 +0700 Subject: [PATCH 018/355] ...Revert AffectsHP->AffectsHp, add HP abbrev --- osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs | 2 +- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- osu.sln.DotSettings | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index ca81b13053..4663d00bdc 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - public override bool AffectsHp => false; + public override bool AffectsHP => false; protected override int NumericResultFor(HitResult result) => 0; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index f4dd90e93b..386495bf1b 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements /// /// Whether this should affect user's hitpoints. /// - public virtual bool AffectsHp => true; + public virtual bool AffectsHP => true; /// /// Computes the numeric result value for the combo portion of the score. diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index 67b113e795..2665540d07 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -6,7 +6,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoStrongJudgement : TaikoJudgement { // MainObject already changes the HP - public override bool AffectsHp => false; + public override bool AffectsHP => false; public override bool AffectsCombo => false; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs index 8a9a023c22..8dd03796ea 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - public override bool AffectsHp => false; + public override bool AffectsHP => false; protected override int NumericResultFor(HitResult result) { diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 064a7d519b..7569edbdb7 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyResult(result); - if (!((TaikoJudgement)result.Judgement).AffectsHp) + if (!((TaikoJudgement)result.Judgement).AffectsHP) return; bool isSwell = false; diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index d6882282e6..38288bc912 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -200,6 +200,7 @@ GL GLSL HID + HP HUD ID IP From 6b07d4581a68f4f933f657e7186eb682eb52fad8 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Fri, 30 Nov 2018 01:07:15 +0700 Subject: [PATCH 019/355] Fixed too strong HP drain --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 7569edbdb7..46706e5977 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// The maximum HP deducted for a . /// This occurs when HP Drain = 10. /// - private const double hp_miss_max = -0.12; + private const double hp_miss_max = -0.012; /// /// The HP awarded for a hit. From 743598a1acfe9fea9bd30aaab81d197eaa4b8192 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Fri, 30 Nov 2018 01:33:04 +0700 Subject: [PATCH 020/355] Decrease taiko swell HP drain --- .../Scoring/TaikoScoreProcessor.cs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 46706e5977..b791d889ee 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -40,6 +40,25 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// private const double hp_miss_max = -0.012; + + /// + /// The minimum HP deducted for a swell . + /// This occurs when HP Drain = 0. + /// + private const double swell_hp_miss_min = -0.0012; + + /// + /// The median HP deducted for a swell . + /// This occurs when HP Drain = 5. + /// + private const double swell_hp_miss_mid = -0.0045; + + /// + /// The maximum HP deducted for a swell . + /// This occurs when HP Drain = 10. + /// + private const double swell_hp_miss_max = -0.0084; + /// /// The HP awarded for a hit. /// @@ -58,6 +77,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring private double hpIncreaseGreat; private double hpIncreaseGood; private double hpIncreaseMiss; + private double hpIncreaseMissSwell; public TaikoScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) @@ -74,6 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring hpIncreaseGreat = hpMultiplierNormal * hp_hit_great; hpIncreaseGood = hpMultiplierNormal * hp_hit_good; hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); + hpIncreaseMissSwell = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, swell_hp_miss_min, swell_hp_miss_mid, swell_hp_miss_max); } protected override void ApplyResult(JudgementResult result) @@ -94,7 +115,9 @@ namespace osu.Game.Rulesets.Taiko.Scoring { case HitResult.Miss: // Missing ticks shouldn't drop HP - if (!isTick) + if (isSwell) + Health.Value += hpIncreaseMissSwell; + else if (!isTick) Health.Value += hpIncreaseMiss; break; case HitResult.Good: From 51c16867d58941c0ccedffd9201b80eeb789df31 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 3 Dec 2018 17:50:39 +0900 Subject: [PATCH 021/355] Remove type conversion from LoungeTab to RoomAvailability --- osu.Game.Tests/Visual/TestCaseMultiScreen.cs | 10 ++++++++++ .../Multi/Screens/Lounge/FilterControl.cs | 19 +++++++++++++++++-- .../Screens/Multi/Screens/Lounge/Lounge.cs | 3 +-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs index 6c22fb020f..9df057806e 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -1,14 +1,24 @@ // 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 NUnit.Framework; using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Screens.Lounge; namespace osu.Game.Tests.Visual { [TestFixture] public class TestCaseMultiScreen : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Multiplayer), + typeof(Lounge), + typeof(FilterControl) + }; + public TestCaseMultiScreen() { Multiplayer multi = new Multiplayer(); diff --git a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs b/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs index 69cb6ad349..716a33c46b 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs @@ -17,11 +17,26 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { DisplayStyleControl.Hide(); } + + public RoomAvailability Availability + { + get + { + switch (Tabs.Current.Value) + { + default: + case LoungeTab.Public: + return RoomAvailability.Public; + case LoungeTab.Private: + return RoomAvailability.FriendsOnly; + } + } + } } public enum LoungeTab { - Public = RoomAvailability.Public, - Private = RoomAvailability.FriendsOnly, + Public, + Private, } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 0af941a668..35f9743761 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -147,8 +147,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge foreach (DrawableRoom r in RoomsContainer.Children) { - r.MatchingFilter = r.MatchingFilter && - r.Room.Availability.Value == (RoomAvailability)Filter.Tabs.Current.Value; + r.MatchingFilter = r.MatchingFilter && r.Room.Availability.Value == Filter.Availability; } } From 20b843e63c86dc8d84217c29ba5a5654c576adae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 3 Dec 2018 17:50:56 +0900 Subject: [PATCH 022/355] Add create tab --- osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs b/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs index 716a33c46b..301e235b79 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs @@ -36,6 +36,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge public enum LoungeTab { + Create, Public, Private, } From 53a54f86341d89250154bedb95636cad6fc21042 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 3 Dec 2018 17:54:10 +0900 Subject: [PATCH 023/355] Renamespace room settings --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 2 +- .../{Screens/Match/Settings => Components}/GameTypePicker.cs | 3 +-- .../Match/Settings => Components}/RoomAvailabilityPicker.cs | 2 +- .../Match/Settings => Components}/RoomSettingsOverlay.cs | 2 +- osu.Game/Screens/Multi/Screens/Match/Match.cs | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) rename osu.Game/Screens/Multi/{Screens/Match/Settings => Components}/GameTypePicker.cs (97%) rename osu.Game/Screens/Multi/{Screens/Match/Settings => Components}/RoomAvailabilityPicker.cs (98%) rename osu.Game/Screens/Multi/{Screens/Match/Settings => Components}/RoomSettingsOverlay.cs (99%) diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index 40742ce709..55e3df679d 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -5,7 +5,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing.Input; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Screens.Match.Settings; +using osu.Game.Screens.Multi.Components; using osuTK.Input; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Screens/Multi/Screens/Match/Settings/GameTypePicker.cs b/osu.Game/Screens/Multi/Components/GameTypePicker.cs similarity index 97% rename from osu.Game/Screens/Multi/Screens/Match/Settings/GameTypePicker.cs rename to osu.Game/Screens/Multi/Components/GameTypePicker.cs index cd8b081b4e..9058185e28 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Settings/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Components/GameTypePicker.cs @@ -9,10 +9,9 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Components; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Match.Settings +namespace osu.Game.Screens.Multi.Components { public class GameTypePicker : TabControl { diff --git a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs similarity index 98% rename from osu.Game/Screens/Multi/Screens/Match/Settings/RoomAvailabilityPicker.cs rename to osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs index 251bd062ec..f0a2a2e8dc 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs @@ -13,7 +13,7 @@ using osu.Game.Online.Multiplayer; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match.Settings +namespace osu.Game.Screens.Multi.Components { public class RoomAvailabilityPicker : TabControl { diff --git a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs similarity index 99% rename from osu.Game/Screens/Multi/Screens/Match/Settings/RoomSettingsOverlay.cs rename to osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index d45ba48f0e..df70e577d5 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Settings/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -14,7 +14,7 @@ using osu.Game.Overlays.SearchableList; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match.Settings +namespace osu.Game.Screens.Multi.Components { public class RoomSettingsOverlay : FocusedOverlayContainer { diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index f7d98df60e..5bfc1f59bd 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Screens.Match.Settings; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Select; using osu.Game.Users; From 6a28e8c696823e3d1575efa6b8a6500837c96289 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 3 Dec 2018 18:30:26 +0900 Subject: [PATCH 024/355] Add settings to lounge --- osu.Game/Online/Multiplayer/Room.cs | 6 +++--- .../Screens/Multi/Screens/Lounge/Lounge.cs | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index b076afbcdb..cb2979d733 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -10,11 +10,11 @@ namespace osu.Game.Online.Multiplayer { public class Room { - public Bindable Name = new Bindable(); + public Bindable Name = new Bindable("My awesome room!"); public Bindable Host = new Bindable(); - public Bindable Status = new Bindable(); + public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); - public Bindable Type = new Bindable(); + public Bindable Type = new Bindable(new GameTypeVersus()); public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(); diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 35f9743761..eb16524776 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { private readonly Container content; private readonly SearchContainer search; + private readonly RoomSettingsOverlay settings; protected readonly FilterControl Filter; protected readonly FillFlowContainer RoomsContainer; @@ -56,7 +57,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { Children = new Drawable[] { - Filter = new FilterControl(), + Filter = new FilterControl { Depth = -1 }, content = new Container { RelativeSizeAxes = Axes.Both, @@ -91,8 +92,17 @@ namespace osu.Game.Screens.Multi.Screens.Lounge RelativeSizeAxes = Axes.Both, Width = 0.45f, }, + new Container + { + RelativeSizeAxes = Axes.Both, + Child = settings = new RoomSettingsOverlay(new Room()) + { + RelativeSizeAxes = Axes.Both, + Height = 0.9f, + }, + }, }, - }, + } }; Filter.Search.Current.ValueChanged += s => filterRooms(); @@ -143,6 +153,11 @@ namespace osu.Game.Screens.Multi.Screens.Lounge private void filterRooms() { + if (Filter.Tabs.Current.Value == LoungeTab.Create) + settings.Show(); + else + settings.Hide(); + search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; foreach (DrawableRoom r in RoomsContainer.Children) From a33865efce7ddd6b212d120478cc401f7f2bd12e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Dec 2018 12:06:05 +0900 Subject: [PATCH 025/355] Fix home button being cancelled by mod select --- osu.Game/Screens/Select/PlaySongSelect.cs | 14 ++++++++------ osu.Game/Screens/Select/SongSelect.cs | 4 +++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index b5d333aee4..2c2a3e31bc 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -85,6 +85,14 @@ namespace osu.Game.Screens.Select } } + protected override void ExitFromBack() + { + if (modSelect.State == Visibility.Visible) + modSelect.Hide(); + + base.ExitFromBack(); + } + protected override void UpdateBeatmap(WorkingBeatmap beatmap) { beatmap.Mods.BindTo(selectedMods); @@ -124,12 +132,6 @@ namespace osu.Game.Screens.Select protected override bool OnExiting(Screen next) { - if (modSelect.State == Visibility.Visible) - { - modSelect.Hide(); - return true; - } - if (base.OnExiting(next)) return true; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index f4af4f9068..66540c6900 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -191,13 +191,15 @@ namespace osu.Game.Screens.Select }); Add(Footer = new Footer { - OnBack = Exit, + OnBack = ExitFromBack, }); FooterPanels.Add(BeatmapOptions = new BeatmapOptionsOverlay()); } } + protected virtual void ExitFromBack() => Exit(); + [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) { From 9fdd48ded2dcc19dff857b0e0c8508559a7552ea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 12:01:30 +0900 Subject: [PATCH 026/355] Add 1ms offset to controlpoint lookup times --- osu.Game/Rulesets/Objects/HitObject.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 024c1d015a..010fc450e0 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -19,6 +19,11 @@ namespace osu.Game.Rulesets.Objects /// public class HitObject { + /// + /// A small adjustment to the start time of control points to account for rounding/precision errors. + /// + private const double control_point_leniency = 1; + /// /// The time at which the HitObject starts. /// @@ -70,7 +75,7 @@ namespace osu.Game.Rulesets.Objects ApplyDefaultsToSelf(controlPointInfo, difficulty); // This is done here since ApplyDefaultsToSelf may be used to determine the end time - SampleControlPoint = controlPointInfo.SamplePointAt((this as IHasEndTime)?.EndTime ?? StartTime); + SampleControlPoint = controlPointInfo.SamplePointAt(((this as IHasEndTime)?.EndTime ?? StartTime) + control_point_leniency); nestedHitObjects.Clear(); @@ -87,7 +92,7 @@ namespace osu.Game.Rulesets.Objects protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { - Kiai = controlPointInfo.EffectPointAt(StartTime).KiaiMode; + Kiai = controlPointInfo.EffectPointAt(StartTime + control_point_leniency).KiaiMode; if (HitWindows == null) HitWindows = CreateHitWindows(); From 415349e6ef0ce2b512322bc40cc630f149017d2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Dec 2018 12:14:26 +0900 Subject: [PATCH 027/355] Add missing return --- osu.Game/Screens/Select/PlaySongSelect.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 2c2a3e31bc..0e3dfcf284 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -88,7 +88,10 @@ namespace osu.Game.Screens.Select protected override void ExitFromBack() { if (modSelect.State == Visibility.Visible) + { modSelect.Hide(); + return; + } base.ExitFromBack(); } From e22cefc27d8139841f9adee55959493f21423b30 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 3 Dec 2018 20:50:40 +0900 Subject: [PATCH 028/355] Immediately select newly-created rooms --- osu.Game/Online/Multiplayer/Room.cs | 3 +- .../Screens/Multi/Components/DrawableRoom.cs | 20 +------ .../Multi/Components/RoomSettingsOverlay.cs | 15 ++++- .../Screens/Multi/Screens/Lounge/Lounge.cs | 59 +++++++++++-------- osu.Game/Screens/Multi/Screens/Match/Match.cs | 2 + .../Multi/Screens/Match/Participants.cs | 3 +- 6 files changed, 58 insertions(+), 44 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index cb2979d733..f4885b6a4a 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Users; @@ -17,6 +18,6 @@ namespace osu.Game.Online.Multiplayer public Bindable Type = new Bindable(new GameTypeVersus()); public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); - public Bindable> Participants = new Bindable>(); + public Bindable> Participants = new Bindable>(Enumerable.Empty()); } } diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 05ec2f0fac..c5fac7170f 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens.Multi.Components private const float side_strip_width = 5; private const float cover_width = 145; + public Action SelectionRequested; + private readonly Box selectionBox; private readonly Bindable nameBind = new Bindable(); @@ -76,17 +78,6 @@ namespace osu.Game.Screens.Multi.Components } } - private Action action; - public new Action Action - { - get { return action; } - set - { - action = value; - Enabled.Value = action != null; - } - } - public event Action StateChanged; public DrawableRoom(Room room) @@ -248,12 +239,7 @@ namespace osu.Game.Screens.Multi.Components protected override bool OnClick(ClickEvent e) { - if (Enabled.Value) - { - Action?.Invoke(this); - State = SelectionState.Selected; - } - + State = SelectionState.Selected; return true; } } diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index df70e577d5..b3d7937433 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.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; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -21,6 +22,16 @@ namespace osu.Game.Screens.Multi.Components private const float transition_duration = 350; private const float field_padding = 45; + /// + /// Invoked when room settings were applied. + /// + public Action Applied; + + /// + /// The room which settings are being applied to. + /// + public readonly Room Room; + private readonly Bindable nameBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); @@ -36,6 +47,8 @@ namespace osu.Game.Screens.Multi.Components public RoomSettingsOverlay(Room room) { + Room = room; + Masking = true; Child = content = new Container @@ -185,7 +198,7 @@ namespace osu.Game.Screens.Multi.Components else maxParticipantsBind.Value = null; - Hide(); + Applied?.Invoke(); } private class SettingsTextBox : OsuTextBox diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index eb16524776..96728c01f9 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -30,29 +29,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override Container TransitionContent => content; - private IEnumerable rooms; - public IEnumerable Rooms - { - get { return rooms; } - set - { - if (Equals(value, rooms)) return; - rooms = value; - - var enumerable = rooms.ToList(); - - RoomsContainer.Children = enumerable.Select(r => new DrawableRoom(r) - { - Action = didSelect, - }).ToList(); - - if (!enumerable.Contains(Inspector.Room)) - Inspector.Room = null; - - filterRooms(); - } - } - public Lounge() { Children = new Drawable[] @@ -108,6 +84,12 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; + + settings.Applied = () => + { + var drawableRoom = addRoom(settings.Room); + drawableRoom.State = SelectionState.Selected; + }; } protected override void UpdateAfterChildren() @@ -122,6 +104,35 @@ namespace osu.Game.Screens.Multi.Screens.Lounge }; } + public IEnumerable Rooms + { + set + { + RoomsContainer.ForEach(r => r.Action = null); + RoomsContainer.Clear(); + + foreach (var room in value) + addRoom(room); + } + } + + private DrawableRoom addRoom(Room room) + { + var drawableRoom = new DrawableRoom(room); + + drawableRoom.StateChanged += s => + { + if (s == SelectionState.Selected) + didSelect(drawableRoom); + }; + + RoomsContainer.Add(drawableRoom); + + filterRooms(); + + return drawableRoom; + } + protected override void OnFocus(FocusEvent e) { GetContainingInputManager().ChangeFocus(Filter.Search); diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 5bfc1f59bd..339db2e158 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -88,6 +88,8 @@ namespace osu.Game.Screens.Multi.Screens.Match header.Tabs.Current.Value = MatchHeaderPage.Room; }; + settings.Applied = () => settings.Hide(); + nameBind.BindTo(room.Name); nameBind.BindValueChanged(n => info.Name = n, true); diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Screens/Match/Participants.cs index 55541a1acd..a5ac93fffc 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Participants.cs @@ -19,7 +19,8 @@ namespace osu.Game.Screens.Multi.Screens.Match public IEnumerable Users { - set { + set + { usersFlow.Children = value.Select(u => new UserPanel(u) { Anchor = Anchor.TopCentre, From d8739d9dee1f0cb3e42608c0a98d7459e9958c45 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 15:25:41 +0900 Subject: [PATCH 029/355] Fix creating a new room re-using the existing model --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 2 +- .../Multi/Components/RoomSettingsOverlay.cs | 44 ++++++++++++++----- .../Screens/Multi/Screens/Lounge/Lounge.cs | 6 ++- osu.Game/Screens/Multi/Screens/Match/Match.cs | 3 +- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index 55e3df679d..83e589b260 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual set => TypePicker.Current.Value = value; } - public TestRoomSettingsOverlay(Room room) : base(room) + public TestRoomSettingsOverlay(Room room) : base() { } diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index b3d7937433..896017b219 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -27,11 +27,6 @@ namespace osu.Game.Screens.Multi.Components /// public Action Applied; - /// - /// The room which settings are being applied to. - /// - public readonly Room Room; - private readonly Bindable nameBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); @@ -45,10 +40,8 @@ namespace osu.Game.Screens.Multi.Components protected readonly GameTypePicker TypePicker; protected readonly TriangleButton ApplyButton; - public RoomSettingsOverlay(Room room) + public RoomSettingsOverlay() { - Room = room; - Masking = true; Child = content = new Container @@ -156,10 +149,7 @@ namespace osu.Game.Screens.Multi.Components typeBind.ValueChanged += t => TypePicker.Current.Value = t; maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); - nameBind.BindTo(room.Name); - availabilityBind.BindTo(room.Availability); - typeBind.BindTo(room.Type); - maxParticipantsBind.BindTo(room.MaxParticipants); + Room = new Room(); } [BackgroundDependencyLoader] @@ -168,6 +158,36 @@ namespace osu.Game.Screens.Multi.Components typeLabel.Colour = colours.Yellow; } + private Room room; + + /// + /// The room which settings are being applied to. + /// + public Room Room + { + get => room; + set + { + if (room == value) + return; + + room = value; + + nameBind.UnbindBindings(); + availabilityBind.UnbindBindings(); + typeBind.UnbindBindings(); + maxParticipantsBind.UnbindBindings(); + + if (room != null) + { + nameBind.BindTo(room.Name); + availabilityBind.BindTo(room.Availability); + typeBind.BindTo(room.Type); + maxParticipantsBind.BindTo(room.MaxParticipants); + } + } + } + protected override void PopIn() { // reapply the rooms values if the overlay was completely closed diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 96728c01f9..475490e399 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -71,10 +71,11 @@ namespace osu.Game.Screens.Multi.Screens.Lounge new Container { RelativeSizeAxes = Axes.Both, - Child = settings = new RoomSettingsOverlay(new Room()) + Child = settings = new RoomSettingsOverlay { RelativeSizeAxes = Axes.Both, Height = 0.9f, + Room = new Room() }, }, }, @@ -153,6 +154,9 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override void OnResuming(Screen last) { base.OnResuming(last); + + settings.Room = new Room(); + Filter.Search.HoldFocus = true; } diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 339db2e158..f0f7a1dd6b 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -57,10 +57,11 @@ namespace osu.Game.Screens.Multi.Screens.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = settings = new RoomSettingsOverlay(room) + Child = settings = new RoomSettingsOverlay { RelativeSizeAxes = Axes.Both, Height = 0.9f, + Room = room }, }, }; From a02e025f06a1e17971daabbce53c3cf95b8efb4c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 15:26:06 +0900 Subject: [PATCH 030/355] Fix selections not working anymore --- .../Screens/Multi/Components/DrawableRoom.cs | 6 +-- .../Screens/Multi/Screens/Lounge/Lounge.cs | 49 ++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index c5fac7170f..2f26f53e8b 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens.Multi.Components private const float side_strip_width = 5; private const float cover_width = 145; + public event Action StateChanged; + public Action SelectionRequested; private readonly Box selectionBox; @@ -78,8 +80,6 @@ namespace osu.Game.Screens.Multi.Components } } - public event Action StateChanged; - public DrawableRoom(Room room) { Room = room; @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Multi.Components protected override bool OnClick(ClickEvent e) { - State = SelectionState.Selected; + SelectionRequested?.Invoke(); return true; } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 475490e399..e820b23e56 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Screens; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; @@ -86,11 +87,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; - settings.Applied = () => - { - var drawableRoom = addRoom(settings.Room); - drawableRoom.State = SelectionState.Selected; - }; + settings.Applied = () => createRoom(settings.Room); } protected override void UpdateAfterChildren() @@ -121,11 +118,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { var drawableRoom = new DrawableRoom(room); - drawableRoom.StateChanged += s => - { - if (s == SelectionState.Selected) - didSelect(drawableRoom); - }; + drawableRoom.SelectionRequested = () => selectionRequested(drawableRoom); RoomsContainer.Add(drawableRoom); @@ -163,6 +156,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override void OnSuspending(Screen next) { base.OnSuspending(next); + Filter.Search.HoldFocus = false; } @@ -181,19 +175,38 @@ namespace osu.Game.Screens.Multi.Screens.Lounge } } - private void didSelect(DrawableRoom room) + private void selectionRequested(DrawableRoom room) { - RoomsContainer.Children.ForEach(c => + if (room.State == SelectionState.Selected) + openRoom(room); + else { - if (c != room) - c.State = SelectionState.NotSelected; - }); + RoomsContainer.ForEach(c => c.State = c == room ? SelectionState.Selected : SelectionState.NotSelected); + Inspector.Room = room.Room; + } + } + private void openRoom(DrawableRoom room) + { + if (!IsCurrentScreen) + return; + + RoomsContainer.ForEach(c => c.State = c == room ? SelectionState.Selected : SelectionState.NotSelected); Inspector.Room = room.Room; - // open the room if its selected and is clicked again - if (room.State == SelectionState.Selected) - Push(new Match.Match(room.Room)); + Push(new Match.Match(room.Room)); + } + + private void createRoom(Room room) + { + openRoom(addRoom(room)); + + this.Delay(WaveContainer.APPEAR_DURATION).Schedule(() => + { + Filter.Tabs.Current.Value = LoungeTab.Public; + settings.Hide(); + settings.FinishTransforms(true); + }); } private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren From 6e5716c3f3ba5d6e782cf1d535a9a9666238c702 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 15:31:48 +0900 Subject: [PATCH 031/355] Adjust transition --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 4 ---- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 10 +--------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index 83e589b260..f4dce329c1 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -105,10 +105,6 @@ namespace osu.Game.Tests.Visual set => TypePicker.Current.Value = value; } - public TestRoomSettingsOverlay(Room room) : base() - { - } - public void ClickApplyButton(ManualInputManager inputManager) { inputManager.MoveMouseTo(ApplyButton); diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index e820b23e56..30da448dde 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Screens; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; @@ -156,7 +155,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override void OnSuspending(Screen next) { base.OnSuspending(next); - Filter.Search.HoldFocus = false; } @@ -200,13 +198,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge private void createRoom(Room room) { openRoom(addRoom(room)); - - this.Delay(WaveContainer.APPEAR_DURATION).Schedule(() => - { - Filter.Tabs.Current.Value = LoungeTab.Public; - settings.Hide(); - settings.FinishTransforms(true); - }); + Filter.Tabs.Current.Value = LoungeTab.Public; } private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren From f2a57ce270363407d088b3096ab9bd7662f56667 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 17:23:58 +0900 Subject: [PATCH 032/355] Fix room host not being set --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 2 +- .../Multi/Components/CreateRoomOverlay.cs | 20 +++++++++++++++++++ .../Screens/Multi/Screens/Lounge/Lounge.cs | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index f4dce329c1..e62afec6b4 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual MaxParticipants = { Value = 10 }, }; - Add(overlay = new TestRoomSettingsOverlay(room) + Add(overlay = new TestRoomSettingsOverlay { RelativeSizeAxes = Axes.Both, Height = 0.75f, diff --git a/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs b/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs new file mode 100644 index 0000000000..7e08e980a3 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Online.API; + +namespace osu.Game.Screens.Multi.Components +{ + public class CreateRoomOverlay : RoomSettingsOverlay + { + [Resolved] + private APIAccess api { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + Room.Host.Value = api.LocalUser; + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 30da448dde..26d25aabfc 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge new Container { RelativeSizeAxes = Axes.Both, - Child = settings = new RoomSettingsOverlay + Child = settings = new CreateRoomOverlay { RelativeSizeAxes = Axes.Both, Height = 0.9f, From b251129c596a62841f34c9830f75e8c5e2f6a397 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 17:43:27 +0900 Subject: [PATCH 033/355] Block going into multiplayer while logged out --- osu.Game/Screens/Menu/ButtonSystem.cs | 33 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index ae1f27610b..943dfa53af 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -17,7 +17,9 @@ using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Input; using osu.Game.Input.Bindings; +using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -90,7 +92,7 @@ namespace osu.Game.Screens.Menu buttonArea.Flow.CentreTarget = iconFacade; buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.fa_user, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P)); - buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), () => OnMulti?.Invoke(), 0, Key.M)); + buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), onMulti, 0, Key.M)); buttonsPlay.Add(new Button(@"chart", @"button-generic-select", FontAwesome.fa_osu_charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke())); buttonsPlay.ForEach(b => b.VisibleState = ButtonSystemState.Play); @@ -103,19 +105,40 @@ namespace osu.Game.Screens.Menu buttonArea.AddRange(buttonsTopLevel); } - private OsuGame game; + [Resolved] + private OsuGame game { get; set; } + + [Resolved] + private APIAccess api { get; set; } + + [Resolved] + private NotificationOverlay notifications { get; set; } [BackgroundDependencyLoader(true)] - private void load(AudioManager audio, OsuGame game, IdleTracker idleTracker) + private void load(AudioManager audio, IdleTracker idleTracker) { - this.game = game; - isIdle.ValueChanged += updateIdleState; + if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); sampleBack = audio.Sample.Get(@"Menu/button-back-select"); } + private void onMulti() + { + if (!api.IsLoggedIn) + { + notifications.Post(new SimpleNotification + { + Text = "You gotta be logged in to multi 'yo!", + Icon = FontAwesome.fa_globe + }); + + return; + } + OnMulti?.Invoke(); + } + private void updateIdleState(bool isIdle) { if (isIdle && State != ButtonSystemState.Exit) From a7ac544e12c245038ee7afe0d39fef604a5f1ad5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 17:43:44 +0900 Subject: [PATCH 034/355] Add interface for the multiplayer screen short title --- osu.Game/Screens/Multi/Header.cs | 2 +- osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs | 10 ++++++++++ osu.Game/Screens/Multi/Screens/Match/Match.cs | 3 ++- osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs | 7 ++----- osu.Game/Screens/Select/MatchSongSelect.cs | 6 +++++- 5 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 6bd300eadc..612a3e6993 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenType.Text = ((MultiplayerScreen)s).Type.ToLowerInvariant(); + breadcrumbs.Current.ValueChanged += s => screenType.Text = ((IMultiplayerScreen)s).ShortTitle.ToLowerInvariant(); breadcrumbs.Current.TriggerChange(); } diff --git a/osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs new file mode 100644 index 0000000000..0b6ebc3716 --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Screens.Multi.Screens +{ + public interface IMultiplayerScreen + { + string ShortTitle { get; } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index f0f7a1dd6b..2dbe0a9c3a 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -28,9 +28,10 @@ namespace osu.Game.Screens.Multi.Screens.Match protected override Container TransitionContent => participants; - public override string Type => "room"; public override string Title => room.Name.Value; + public override string ShortTitle => "room"; + public Match(Room room) { this.room = room; diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs index 00c2613d54..fd866a5fef 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -8,14 +8,11 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Multi.Screens { - public abstract class MultiplayerScreen : OsuScreen + public abstract class MultiplayerScreen : OsuScreen, IMultiplayerScreen { protected virtual Container TransitionContent => Content; - /// - /// The type to display in the title of the . - /// - public virtual string Type => Title; + public virtual string ShortTitle => Title; protected override void OnEntering(Screen last) { diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 339392d5cf..28525215fb 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Screens.Multi.Screens; + namespace osu.Game.Screens.Select { - public class MatchSongSelect : SongSelect + public class MatchSongSelect : SongSelect, IMultiplayerScreen { + public string ShortTitle => "song selection"; + protected override bool OnStart() { if (IsCurrentScreen) Exit(); From c469d12d63be181e6d89c565419b1b4122030167 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 18:18:17 +0900 Subject: [PATCH 035/355] Set room host when the room is refreshed --- .../Screens/Multi/Components/CreateRoomOverlay.cs | 13 +++++++++++++ .../Screens/Multi/Components/RoomSettingsOverlay.cs | 2 +- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 12 ++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs b/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs index 7e08e980a3..3a6224da26 100644 --- a/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs +++ b/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.Multi.Components { @@ -16,5 +17,17 @@ namespace osu.Game.Screens.Multi.Components { Room.Host.Value = api.LocalUser; } + + public override Room Room + { + get => base.Room; + set + { + base.Room = value; + + if (api != null && value != null) + value.Host.Value = api.LocalUser; + } + } } } diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index 896017b219..f50eefe4c6 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -163,7 +163,7 @@ namespace osu.Game.Screens.Multi.Components /// /// The room which settings are being applied to. /// - public Room Room + public virtual Room Room { get => room; set diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 26d25aabfc..f307032600 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { private readonly Container content; private readonly SearchContainer search; - private readonly RoomSettingsOverlay settings; + private readonly CreateRoomOverlay createRoomOverlay; protected readonly FilterControl Filter; protected readonly FillFlowContainer RoomsContainer; @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge new Container { RelativeSizeAxes = Axes.Both, - Child = settings = new CreateRoomOverlay + Child = createRoomOverlay = new CreateRoomOverlay { RelativeSizeAxes = Axes.Both, Height = 0.9f, @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; - settings.Applied = () => createRoom(settings.Room); + createRoomOverlay.Applied = () => createRoom(createRoomOverlay.Room); } protected override void UpdateAfterChildren() @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { base.OnResuming(last); - settings.Room = new Room(); + createRoomOverlay.Room = new Room(); Filter.Search.HoldFocus = true; } @@ -161,9 +161,9 @@ namespace osu.Game.Screens.Multi.Screens.Lounge private void filterRooms() { if (Filter.Tabs.Current.Value == LoungeTab.Create) - settings.Show(); + createRoomOverlay.Show(); else - settings.Hide(); + createRoomOverlay.Hide(); search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; From ec837907348eeeef243d660d99d8293953411f94 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 18:58:45 +0900 Subject: [PATCH 036/355] Add timeshift game type --- osu.Game.Tests/Visual/TestCaseMatch.cs | 9 +++++ osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 8 +++++ osu.Game/Online/Multiplayer/GameType.cs | 33 +++++++++++++++++++ osu.Game/Online/Multiplayer/Room.cs | 2 +- .../Multi/Components/GameTypePicker.cs | 15 ++++++++- 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index bb22358425..ae19b9720e 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -1,11 +1,14 @@ // 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 NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Screens.Match; using osu.Game.Users; @@ -14,6 +17,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseMatch : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TestCaseMatch), + typeof(GameTypePicker) + }; + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index e62afec6b4..af41563e30 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.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 System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing.Input; @@ -13,6 +15,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseRoomSettings : ManualInputManagerTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RoomSettingsOverlay), + typeof(GameTypePicker) + }; + private readonly Room room; private readonly TestRoomSettingsOverlay overlay; diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs index 8d39e8f59d..ced6d7d318 100644 --- a/osu.Game/Online/Multiplayer/GameType.cs +++ b/osu.Game/Online/Multiplayer/GameType.cs @@ -13,6 +13,9 @@ namespace osu.Game.Online.Multiplayer public abstract class GameType { public abstract string Name { get; } + + public abstract bool IsAvailable { get; } + public abstract Drawable GetIcon(OsuColour colours, float size); public override int GetHashCode() => GetType().GetHashCode(); @@ -22,6 +25,9 @@ namespace osu.Game.Online.Multiplayer public class GameTypeTag : GameType { public override string Name => "Tag"; + + public override bool IsAvailable => false; + public override Drawable GetIcon(OsuColour colours, float size) { return new SpriteIcon @@ -39,6 +45,9 @@ namespace osu.Game.Online.Multiplayer public class GameTypeVersus : GameType { public override string Name => "Versus"; + + public override bool IsAvailable => false; + public override Drawable GetIcon(OsuColour colours, float size) { return new VersusRow(colours.Blue, colours.Blue, size * 0.6f) @@ -52,6 +61,9 @@ namespace osu.Game.Online.Multiplayer public class GameTypeTagTeam : GameType { public override string Name => "Tag Team"; + + public override bool IsAvailable => false; + public override Drawable GetIcon(OsuColour colours, float size) { return new FillFlowContainer @@ -85,6 +97,9 @@ namespace osu.Game.Online.Multiplayer public class GameTypeTeamVersus : GameType { public override string Name => "Team Versus"; + + public override bool IsAvailable => false; + public override Drawable GetIcon(OsuColour colours, float size) { return new FillFlowContainer @@ -146,4 +161,22 @@ namespace osu.Game.Online.Multiplayer }; } } + + public class GameTypeTimeshift : GameType + { + public override string Name => "Timeshift"; + + public override bool IsAvailable => true; + + public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.fa_osu_charts, + X = -2, // The icon is off-centre + Size = new Vector2(size), + Colour = colours.Blue, + Shadow = false + }; + } } diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index f4885b6a4a..8395b7e638 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -15,7 +15,7 @@ namespace osu.Game.Online.Multiplayer public Bindable Host = new Bindable(); public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); - public Bindable Type = new Bindable(new GameTypeVersus()); + public Bindable Type = new Bindable(new GameTypeTimeshift()); public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(Enumerable.Empty()); diff --git a/osu.Game/Screens/Multi/Components/GameTypePicker.cs b/osu.Game/Screens/Multi/Components/GameTypePicker.cs index 9058185e28..9cd1a7dc14 100644 --- a/osu.Game/Screens/Multi/Components/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Components/GameTypePicker.cs @@ -19,6 +19,7 @@ namespace osu.Game.Screens.Multi.Components private const float selection_width = 3; protected override TabItem CreateTabItem(GameType value) => new GameTypePickerItem(value); + protected override Dropdown CreateDropdown() => null; public GameTypePicker() @@ -30,6 +31,7 @@ namespace osu.Game.Screens.Multi.Components AddItem(new GameTypeVersus()); AddItem(new GameTypeTagTeam()); AddItem(new GameTypeTeamVersus()); + AddItem(new GameTypeTimeshift()); } private class GameTypePickerItem : TabItem @@ -38,7 +40,8 @@ namespace osu.Game.Screens.Multi.Components private readonly CircularContainer hover, selection; - public GameTypePickerItem(GameType value) : base(value) + public GameTypePickerItem(GameType value) + : base(value) { AutoSizeAxes = Axes.Both; @@ -81,6 +84,9 @@ namespace osu.Game.Screens.Multi.Components private void load(OsuColour colours) { selection.Colour = colours.Yellow; + + if (!Value.IsAvailable) + Colour = colours.Gray5; } protected override bool OnHover(HoverEvent e) @@ -95,6 +101,13 @@ namespace osu.Game.Screens.Multi.Components base.OnHoverLost(e); } + protected override bool OnClick(ClickEvent e) + { + if (!Value.IsAvailable) + return true; + return base.OnClick(e); + } + protected override void OnActivated() { selection.FadeIn(transition_duration, Easing.OutQuint); From ca91dfa09157a2dc92805acfd1adf32ec460f765 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 4 Dec 2018 19:18:39 +0900 Subject: [PATCH 037/355] Make hudoverlay always present --- osu.Game/Screens/Play/HUDOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 98be0871a1..11cee98bdf 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Play Add(content = new Container { RelativeSizeAxes = Axes.Both, - + AlwaysPresent = true, // The hud may be hidden but certain elements may need to still be updated Children = new Drawable[] { ComboCounter = CreateComboCounter(), From 7d692939fc63e78f4787b552ff2cebc437b1659f Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Tue, 4 Dec 2018 21:20:44 +0700 Subject: [PATCH 038/355] Fixed being able to miss taiko objects by hitting them too early Revamped taiko HP system --- .../Judgements/TaikoDrumRollJudgement.cs | 4 +- .../Judgements/TaikoDrumRollTickJudgement.cs | 11 ++++ .../Judgements/TaikoJudgement.cs | 34 +++++++++--- .../Judgements/TaikoStrongJudgement.cs | 4 +- .../Judgements/TaikoSwellJudgement.cs | 11 +++- .../Judgements/TaikoSwellTickJudgement.cs | 13 +---- .../Objects/Drawables/DrawableHit.cs | 2 +- .../Scoring/TaikoScoreProcessor.cs | 53 +++++-------------- osu.sln.DotSettings | 1 - 9 files changed, 70 insertions(+), 63 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 4663d00bdc..e1a630e6b7 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -9,8 +9,8 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - public override bool AffectsHP => false; - protected override int NumericResultFor(HitResult result) => 0; + + protected override double HealthIncreaseFor(HitResult result) => 0; } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 446dd0d11b..b2adf45bab 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -19,5 +19,16 @@ namespace osu.Game.Rulesets.Taiko.Judgements return 200; } } + + protected override double HealthIncreaseFor(HitResult result) + { + switch(result) + { + default: + return 0; + case HitResult.Great: + return 0.0000003; + } + } } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 386495bf1b..f43227ecca 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -9,12 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoJudgement : Judgement { public override HitResult MaxResult => HitResult.Great; - - /// - /// Whether this should affect user's hitpoints. - /// - public virtual bool AffectsHP => true; - + /// /// Computes the numeric result value for the combo portion of the score. /// @@ -32,5 +27,32 @@ namespace osu.Game.Rulesets.Taiko.Judgements return 300; } } + + /// + /// Retrieves the numeric health increase of a . + /// + /// The to find the numeric health increase for. + /// The numeric health increase of . + protected virtual double HealthIncreaseFor(HitResult result) + { + switch (result) + { + default: + return 0; + case HitResult.Miss: + return -1.0; + case HitResult.Good: + return 1.1; + case HitResult.Great: + return 3.0; + } + } + + /// + /// Retrieves the numeric health increase of a . + /// + /// The to find the numeric health increase for. + /// The numeric health increase of . + public double HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index 2665540d07..81dfaf4cc3 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -1,12 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Scoring; + namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoStrongJudgement : TaikoJudgement { // MainObject already changes the HP - public override bool AffectsHP => false; + protected override double HealthIncreaseFor(HitResult result) => 0; public override bool AffectsCombo => false; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index b913f5d730..ca89d4d0e5 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -9,6 +9,15 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - protected override int NumericResultFor(HitResult result) => 0; + protected override double HealthIncreaseFor(HitResult result) + { + switch(result) + { + default: + return 0; + case HitResult.Miss: + return -0.65; + } + } } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs index 8dd03796ea..448c16dad6 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs @@ -9,17 +9,8 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - public override bool AffectsHP => false; + protected override int NumericResultFor(HitResult result) => 0; - protected override int NumericResultFor(HitResult result) - { - switch (result) - { - default: - return 0; - case HitResult.Great: - return 300; - } - } + protected override double HealthIncreaseFor(HitResult result) => 0; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 48731388cb..8c19e64de6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } var result = HitObject.HitWindows.ResultFor(timeOffset); - if (result == HitResult.None) + if (result <= HitResult.Miss) return; if (!validActionPressed) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index b791d889ee..50989cef7c 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -73,11 +73,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; - private double hpIncreaseTick; - private double hpIncreaseGreat; - private double hpIncreaseGood; - private double hpIncreaseMiss; - private double hpIncreaseMissSwell; + private double hpMultiplier; + private double hpMissMultiplier; public TaikoScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) @@ -88,49 +85,25 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyBeatmap(beatmap); - double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); + hpMultiplier = 0.01 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); - hpIncreaseTick = hp_hit_tick; - hpIncreaseGreat = hpMultiplierNormal * hp_hit_great; - hpIncreaseGood = hpMultiplierNormal * hp_hit_good; - hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); - hpIncreaseMissSwell = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, swell_hp_miss_min, swell_hp_miss_mid, swell_hp_miss_max); + hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); } protected override void ApplyResult(JudgementResult result) { base.ApplyResult(result); - if (!((TaikoJudgement)result.Judgement).AffectsHP) - return; - - bool isSwell = false; - bool isTick = result.Judgement is TaikoDrumRollTickJudgement; - - if(!isTick) - isSwell = result.Judgement is TaikoSwellJudgement; - - // Apply HP changes - switch (result.Type) + if (result.Judgement is TaikoJudgement taikoJudgement) { - case HitResult.Miss: - // Missing ticks shouldn't drop HP - if (isSwell) - Health.Value += hpIncreaseMissSwell; - else if (!isTick) - Health.Value += hpIncreaseMiss; - break; - case HitResult.Good: - // Swells shouldn't increase HP - if (!isSwell) - Health.Value += hpIncreaseGood; - break; - case HitResult.Great: - if (isTick) - Health.Value += hpIncreaseTick; - else if(!isSwell) - Health.Value += hpIncreaseGreat; - break; + double hpIncrease = taikoJudgement.HealthIncreaseFor(result); + + if (result.Type == HitResult.Miss) + hpIncrease *= hpMissMultiplier; + else + hpIncrease *= hpMultiplier; + + Health.Value += hpIncrease; } } diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 38288bc912..d6882282e6 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -200,7 +200,6 @@ GL GLSL HID - HP HUD ID IP From 1975e11fcc8b075044c3f03f1fd3d2bf949136d2 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Tue, 4 Dec 2018 21:28:36 +0700 Subject: [PATCH 039/355] Yet Another Whitespace Fix --- osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index f43227ecca..244a00ffb9 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoJudgement : Judgement { public override HitResult MaxResult => HitResult.Great; - + /// /// Computes the numeric result value for the combo portion of the score. /// From f2b806d3033509adedddaf57a130969297f299d3 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Tue, 4 Dec 2018 21:36:43 +0700 Subject: [PATCH 040/355] Remove swell miss HP from TaikoScoreProcessor --- .../Scoring/TaikoScoreProcessor.cs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 50989cef7c..40e7f3e12e 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -41,24 +41,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring private const double hp_miss_max = -0.012; - /// - /// The minimum HP deducted for a swell . - /// This occurs when HP Drain = 0. - /// - private const double swell_hp_miss_min = -0.0012; - - /// - /// The median HP deducted for a swell . - /// This occurs when HP Drain = 5. - /// - private const double swell_hp_miss_mid = -0.0045; - - /// - /// The maximum HP deducted for a swell . - /// This occurs when HP Drain = 10. - /// - private const double swell_hp_miss_max = -0.0084; - /// /// The HP awarded for a hit. /// From 6c38db04eed786f67ffc1048073267c5351500d7 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Tue, 4 Dec 2018 21:48:22 +0700 Subject: [PATCH 041/355] Fix switch statement order in taiko judgements --- .../Judgements/TaikoDrumRollTickJudgement.cs | 4 ++-- osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs | 4 ++-- osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index b2adf45bab..0ccc66877c 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -24,10 +24,10 @@ namespace osu.Game.Rulesets.Taiko.Judgements { switch(result) { - default: - return 0; case HitResult.Great: return 0.0000003; + default: + return 0; } } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 244a00ffb9..c3b603746b 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -19,12 +19,12 @@ namespace osu.Game.Rulesets.Taiko.Judgements { switch (result) { - default: - return 0; case HitResult.Good: return 100; case HitResult.Great: return 300; + default: + return 0; } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index ca89d4d0e5..7c525bba6c 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -13,10 +13,10 @@ namespace osu.Game.Rulesets.Taiko.Judgements { switch(result) { - default: - return 0; case HitResult.Miss: return -0.65; + default: + return 0; } } } From c7c5837ec1546f27061d154cb2efeeaea839f172 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 01:45:32 +0900 Subject: [PATCH 042/355] Fix GetWorkingBeatmap potentially loading same beatmap twice This could be seen when using the previous/next buttons in the MusicController while at song select. --- osu.Game/Beatmaps/BeatmapManager.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 8728d776d0..603f3f1d48 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -249,10 +249,13 @@ namespace osu.Game.Beatmaps /// Retrieve a instance for the provided /// /// The beatmap to lookup. - /// The currently loaded . Allows for optimisation where elements are shared with the new beatmap. + /// The currently loaded . Allows for optimisation where elements are shared with the new beatmap. May be returned if beatmapInfo requested matches /// A instance correlating to the provided . public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null) { + if (previous != null && previous.BeatmapInfo.ID == beatmapInfo.ID) + return previous; + if (beatmapInfo?.BeatmapSet == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo) return DefaultBeatmap; From b5ba74a6282e9001456b097153cbe55b47460c32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 02:12:15 +0900 Subject: [PATCH 043/355] Add more specific checks --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 603f3f1d48..c179821a7c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -253,7 +253,7 @@ namespace osu.Game.Beatmaps /// A instance correlating to the provided . public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null) { - if (previous != null && previous.BeatmapInfo.ID == beatmapInfo.ID) + if (beatmapInfo?.ID > 0 && previous != null && previous.BeatmapInfo?.ID == beatmapInfo.ID) return previous; if (beatmapInfo?.BeatmapSet == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo) From 1a974f64ded87e5f1fa575a5b6c8e291cdba5982 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Dec 2018 20:33:29 +0900 Subject: [PATCH 044/355] Initial design for user registration dialog --- .../Objects/Drawables/DrawableOsuHitObject.cs | 6 +- .../Visual/TestCaseAccountCreationOverlay.cs | 19 ++ .../Containers/OsuFocusedOverlayContainer.cs | 1 - .../Graphics/Containers/ShakeContainer.cs | 32 ++- osu.Game/Online/API/APIAccess.cs | 5 + osu.Game/Online/API/RegsitrationRequest.cs | 23 ++ osu.Game/OsuGame.cs | 8 + .../AccountCreation/RegistrationBackground.cs | 45 ++++ osu.Game/Overlays/AccountCreationOverlay.cs | 234 ++++++++++++++++++ .../Sections/General/LoginSettings.cs | 28 ++- osu.Game/osu.Game.csproj | 3 + 11 files changed, 384 insertions(+), 20 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs create mode 100644 osu.Game/Online/API/RegsitrationRequest.cs create mode 100644 osu.Game/Overlays/AccountCreation/RegistrationBackground.cs create mode 100644 osu.Game/Overlays/AccountCreationOverlay.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 2ac46a14f2..56c4ea639b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -21,7 +21,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { - base.AddInternal(shakeContainer = new ShakeContainer { RelativeSizeAxes = Axes.Both }); + base.AddInternal(shakeContainer = new ShakeContainer + { + ShakeDuration = 30, + RelativeSizeAxes = Axes.Both + }); Alpha = 0; } diff --git a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs new file mode 100644 index 0000000000..c8ee86e5fd --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseAccountCreationOverlay : OsuTestCase + { + public TestCaseAccountCreationOverlay() + { + var accountCreation = new AccountCreationOverlay(); + Child = accountCreation; + + accountCreation.State = Visibility.Visible; + } + } +} diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index a24b6594e0..ad46e50344 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -26,7 +26,6 @@ namespace osu.Game.Graphics.Containers private PreviewTrackManager previewTrackManager; - protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index fde4d59f46..6b7b59bbd9 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -11,29 +11,43 @@ namespace osu.Game.Graphics.Containers /// public class ShakeContainer : Container { + /// + /// The length of a single shake. + /// + public float ShakeDuration = 80; + + /// + /// Total number of shakes. May be shortened if possible. + /// + public float TotalShakes = 4; + + /// + /// Pixels of displacement per shake. + /// + public float ShakeMagnitude = 8; + /// /// Shake the contents of this container. /// /// The maximum length the shake should last. - public void Shake(double maximumLength) + public void Shake(double? maximumLength = null) { const float shake_amount = 8; - const float shake_duration = 30; // if we don't have enough time, don't bother shaking. - if (maximumLength < shake_duration * 2) + if (maximumLength < ShakeDuration * 2) return; - var sequence = this.MoveToX(shake_amount, shake_duration / 2, Easing.OutSine).Then() - .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then(); + var sequence = this.MoveToX(shake_amount, ShakeDuration / 2, Easing.OutSine).Then() + .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); // if we don't have enough time for the second shake, skip it. - if (maximumLength > shake_duration * 4) + if (!maximumLength.HasValue || maximumLength >= ShakeDuration * 4) sequence = sequence - .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() - .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then(); + .MoveToX(shake_amount, ShakeDuration, Easing.InOutSine).Then() + .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); - sequence.MoveToX(0, shake_duration / 2, Easing.InSine); + sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); } } } diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 1dda257c95..52bb2f5eeb 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -189,6 +189,11 @@ namespace osu.Game.Online.API this.password = password; } + public void CreateAccount(string email, string username, string password) + { + Debug.Assert(State == APIState.Offline); + } + /// /// Handle a single API request. /// diff --git a/osu.Game/Online/API/RegsitrationRequest.cs b/osu.Game/Online/API/RegsitrationRequest.cs new file mode 100644 index 0000000000..134bf45263 --- /dev/null +++ b/osu.Game/Online/API/RegsitrationRequest.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API +{ + internal class RegsitrationRequest : JsonWebRequest + { + internal string Username; + internal string Email; + internal string Password; + + protected override void PrePerform() + { + AddParameter("user", Username); + AddParameter("user_email", Email); + AddParameter("password", Password); + + base.PrePerform(); + } + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cd40d4793a..a5dd7ab071 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -61,6 +61,8 @@ namespace osu.Game private DialogOverlay dialogOverlay; + private AccountCreationOverlay accountCreation; + private DirectOverlay direct; private SocialOverlay social; @@ -405,6 +407,11 @@ namespace osu.Game Depth = -6, }, overlayContent.Add); + loadComponentSingleFile(accountCreation = new AccountCreationOverlay + { + Depth = -7, + }, overlayContent.Add); + dependencies.Cache(idleTracker); dependencies.Cache(settings); dependencies.Cache(onscreenDisplay); @@ -417,6 +424,7 @@ namespace osu.Game dependencies.Cache(beatmapSetOverlay); dependencies.Cache(notifications); dependencies.Cache(dialogOverlay); + dependencies.Cache(accountCreation); Add(externalLinkOpener = new ExternalLinkOpener()); diff --git a/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs b/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs new file mode 100644 index 0000000000..45c495d142 --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs @@ -0,0 +1,45 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Overlays.AccountCreation +{ + public class AccountCreationBackground : Sprite + { + public AccountCreationBackground() + { + FillMode = FillMode.Fill; + RelativeSizeAxes = Axes.Both; + + Anchor = Anchor.CentreRight; + Origin = Anchor.CentreRight; + } + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) + { + Texture = textures.Get("Backgrounds/registration"); + } + + protected override void LoadComplete() + { + const float x_movement = 80; + + const float initial_move_time = 5000; + const float loop_move_time = 10000; + + base.LoadComplete(); + this.FadeInFromZero(initial_move_time / 4, Easing.OutQuint); + this.MoveToX(x_movement / 2).MoveToX(0, initial_move_time, Easing.OutQuint); + + using (BeginDelayedSequence(initial_move_time)) + { + this + .MoveToX(x_movement, loop_move_time, Easing.InOutSine) + .Then().MoveToX(0, loop_move_time, Easing.InOutSine) + .Loop(); + } + } + } +} diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs new file mode 100644 index 0000000000..b8d428a839 --- /dev/null +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -0,0 +1,234 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osuTK.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.MathUtils; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays.AccountCreation; +using osu.Game.Overlays.Settings; +using osuTK; + +namespace osu.Game.Overlays +{ + public class AccountCreationOverlay : OsuFocusedOverlayContainer, IOnlineComponent + { + private OsuTextFlowContainer usernameDescription; + private OsuTextFlowContainer emailAddressDescription; + private OsuTextFlowContainer passwordDescription; + + private OsuTextBox usernameTextBox; + private OsuTextBox emailTextBox; + private OsuPasswordTextBox passwordTextBox; + + private APIAccess api; + private ShakeContainer registerShake; + private IEnumerable characterCheckText; + + private const float transition_time = 400; + + public AccountCreationOverlay() + { + Size = new Vector2(620, 450); + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + State = Visibility.Visible; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, APIAccess api) + { + this.api = api; + + api.Register(this); + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 5, + Colour = Color4.Black.Opacity(0.2f), + }, + Masking = true, + CornerRadius = 10, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + new DelayedLoadWrapper(new AccountCreationBackground(), 0), + new Container + { + RelativeSizeAxes = Axes.Both, + Width = 0.6f, + AutoSizeDuration = transition_time, + AutoSizeEasing = Easing.OutQuint, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.9f, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + TextSize = 20, + Margin = new MarginPadding { Vertical = 10 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Let's create an account!", + }, + usernameTextBox = new OsuTextBox + { + PlaceholderText = "username", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + usernameDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + }, + emailTextBox = new OsuTextBox + { + PlaceholderText = "email address", + RelativeSizeAxes = Axes.X, + Text = api.ProvidedUsername ?? string.Empty, + TabbableContentContainer = this + }, + emailAddressDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + }, + passwordTextBox = new OsuPasswordTextBox + { + PlaceholderText = "password", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + passwordDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + registerShake = new ShakeContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new SettingsButton + { + Text = "Register", + Margin = new MarginPadding { Vertical = 20 }, + Action = performRegistration + } + } + } + }, + } + }, + } + } + } + } + }; + + usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); + + emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); + emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = "Exo2.0-Bold"); + + passwordDescription.AddText("At least "); + characterCheckText = passwordDescription.AddText("8 characters long"); + passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); + + passwordTextBox.Current.ValueChanged += text => { + characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); + }; + } + + private void performRegistration() + { + var textbox = nextUnfilledTextbox(); + + if (textbox != null) + { + Schedule(() => GetContainingInputManager().ChangeFocus(textbox)); + registerShake.Shake(); + return; + } + + api.CreateAccount(emailTextBox.Text, usernameTextBox.Text, passwordTextBox.Text); + } + + private OsuTextBox nextUnfilledTextbox() + { + OsuTextBox textboxIfUsable(OsuTextBox textbox) => !string.IsNullOrEmpty(textbox.Text) ? null : textbox; + + return textboxIfUsable(usernameTextBox) ?? textboxIfUsable(emailTextBox) ?? textboxIfUsable(passwordTextBox); + } + + protected override void PopIn() + { + base.PopIn(); + this.FadeIn(transition_time, Easing.OutQuint); + + var nextTextbox = nextUnfilledTextbox(); + if (nextTextbox != null) + Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); + } + + protected override void PopOut() + { + base.PopOut(); + this.FadeOut(100); + } + + public void APIStateChanged(APIAccess api, APIState state) + { + switch (state) + { + case APIState.Offline: + case APIState.Failing: + break; + case APIState.Connecting: + break; + case APIState.Online: + break; + } + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 6623fbc73b..0cb6d2d1aa 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -79,7 +79,10 @@ namespace osu.Game.Overlays.Settings.Sections.General Margin = new MarginPadding { Bottom = 5 }, Font = @"Exo2.0-Black", }, - form = new LoginForm() + form = new LoginForm + { + RequestHide = RequestHide + } }; break; case APIState.Failing: @@ -189,6 +192,8 @@ namespace osu.Game.Overlays.Settings.Sections.General private TextBox password; private APIAccess api; + public Action RequestHide; + private void performLogin() { if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) @@ -196,7 +201,7 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, OsuConfigManager config) + private void load(APIAccess api, OsuConfigManager config, AccountCreationOverlay accountCreation) { this.api = api; Direction = FillDirection.Vertical; @@ -207,14 +212,14 @@ namespace osu.Game.Overlays.Settings.Sections.General { username = new OsuTextBox { - PlaceholderText = "Email address", + PlaceholderText = "email address", RelativeSizeAxes = Axes.X, Text = api?.ProvidedUsername ?? string.Empty, TabbableContentContainer = this }, password = new OsuPasswordTextBox { - PlaceholderText = "Password", + PlaceholderText = "password", RelativeSizeAxes = Axes.X, TabbableContentContainer = this, OnCommit = (sender, newText) => performLogin() @@ -237,7 +242,11 @@ namespace osu.Game.Overlays.Settings.Sections.General new SettingsButton { Text = "Register", - //Action = registerLink + Action = () => + { + RequestHide(); + accountCreation.Show(); + } } }; } @@ -322,12 +331,10 @@ namespace osu.Game.Overlays.Settings.Sections.General public const float LABEL_LEFT_MARGIN = 20; private readonly SpriteIcon statusIcon; + public Color4 StatusColour { - set - { - statusIcon.FadeColour(value, 500, Easing.OutQuint); - } + set { statusIcon.FadeColour(value, 500, Easing.OutQuint); } } public UserDropdownHeader() @@ -368,10 +375,13 @@ namespace osu.Game.Overlays.Settings.Sections.General private enum UserAction { Online, + [Description(@"Do not disturb")] DoNotDisturb, + [Description(@"Appear offline")] AppearOffline, + [Description(@"Sign out")] SignOut, } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 85eabb0350..78496830d8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,4 +24,7 @@ + + + From f3f449c749f548938238e1352d88e9d233249c35 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 13:08:35 +0900 Subject: [PATCH 045/355] wip --- osu.Game/Online/API/APIAccess.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 52bb2f5eeb..3c99290080 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -192,6 +192,10 @@ namespace osu.Game.Online.API public void CreateAccount(string email, string username, string password) { Debug.Assert(State == APIState.Offline); + + var req = new RegistrationRequest(); + + req.Perform(); } /// From e7d7e005169abffc7039258041722c184b4eb1a4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Dec 2018 17:01:14 +0900 Subject: [PATCH 046/355] Better disabling of various controls --- osu.Game/Online/Multiplayer/GameType.cs | 12 ----- .../Multi/Components/DisableableTabControl.cs | 44 +++++++++++++++++++ .../Multi/Components/GameTypePicker.cs | 14 +----- .../Components/RoomAvailabilityPicker.cs | 6 +-- .../Multi/Components/RoomSettingsOverlay.cs | 17 +++++++ 5 files changed, 66 insertions(+), 27 deletions(-) create mode 100644 osu.Game/Screens/Multi/Components/DisableableTabControl.cs diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs index ced6d7d318..8c9d635eea 100644 --- a/osu.Game/Online/Multiplayer/GameType.cs +++ b/osu.Game/Online/Multiplayer/GameType.cs @@ -14,8 +14,6 @@ namespace osu.Game.Online.Multiplayer { public abstract string Name { get; } - public abstract bool IsAvailable { get; } - public abstract Drawable GetIcon(OsuColour colours, float size); public override int GetHashCode() => GetType().GetHashCode(); @@ -26,8 +24,6 @@ namespace osu.Game.Online.Multiplayer { public override string Name => "Tag"; - public override bool IsAvailable => false; - public override Drawable GetIcon(OsuColour colours, float size) { return new SpriteIcon @@ -46,8 +42,6 @@ namespace osu.Game.Online.Multiplayer { public override string Name => "Versus"; - public override bool IsAvailable => false; - public override Drawable GetIcon(OsuColour colours, float size) { return new VersusRow(colours.Blue, colours.Blue, size * 0.6f) @@ -62,8 +56,6 @@ namespace osu.Game.Online.Multiplayer { public override string Name => "Tag Team"; - public override bool IsAvailable => false; - public override Drawable GetIcon(OsuColour colours, float size) { return new FillFlowContainer @@ -98,8 +90,6 @@ namespace osu.Game.Online.Multiplayer { public override string Name => "Team Versus"; - public override bool IsAvailable => false; - public override Drawable GetIcon(OsuColour colours, float size) { return new FillFlowContainer @@ -166,8 +156,6 @@ namespace osu.Game.Online.Multiplayer { public override string Name => "Timeshift"; - public override bool IsAvailable => true; - public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs new file mode 100644 index 0000000000..1ca61a2678 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -0,0 +1,44 @@ +// 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.Graphics.UserInterface; +using osu.Framework.Input.Events; + +namespace osu.Game.Screens.Multi.Components +{ + public abstract class DisableableTabControl : TabControl + { + public IEnumerable DisabledItems + { + set + { + foreach (var item in value) + (TabMap[item] as DisableableTabItem)?.Disable(); + } + } + + protected abstract class DisableableTabItem : TabItem + { + protected DisableableTabItem(T value) + : base(value) + { + } + + private bool isDisabled; + + public void Disable() + { + Alpha = 0.2f; + isDisabled = true; + } + + protected override bool OnClick(ClickEvent e) + { + if (isDisabled) + return true; + return base.OnClick(e); + } + } + } +} diff --git a/osu.Game/Screens/Multi/Components/GameTypePicker.cs b/osu.Game/Screens/Multi/Components/GameTypePicker.cs index 9cd1a7dc14..d9619ad35d 100644 --- a/osu.Game/Screens/Multi/Components/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Components/GameTypePicker.cs @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Screens.Multi.Components { - public class GameTypePicker : TabControl + public class GameTypePicker : DisableableTabControl { private const float height = 40; private const float selection_width = 3; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Multi.Components AddItem(new GameTypeTimeshift()); } - private class GameTypePickerItem : TabItem + private class GameTypePickerItem : DisableableTabItem { private const float transition_duration = 200; @@ -84,9 +84,6 @@ namespace osu.Game.Screens.Multi.Components private void load(OsuColour colours) { selection.Colour = colours.Yellow; - - if (!Value.IsAvailable) - Colour = colours.Gray5; } protected override bool OnHover(HoverEvent e) @@ -101,13 +98,6 @@ namespace osu.Game.Screens.Multi.Components base.OnHoverLost(e); } - protected override bool OnClick(ClickEvent e) - { - if (!Value.IsAvailable) - return true; - return base.OnClick(e); - } - protected override void OnActivated() { selection.FadeIn(transition_duration, Easing.OutQuint); diff --git a/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs index f0a2a2e8dc..287add5de1 100644 --- a/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Multi.Components { - public class RoomAvailabilityPicker : TabControl + public class RoomAvailabilityPicker : DisableableTabControl { protected override TabItem CreateTabItem(RoomAvailability value) => new RoomAvailabilityPickerItem(value); protected override Dropdown CreateDropdown() => null; @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Multi.Components AddItem(RoomAvailability.InviteOnly); } - private class RoomAvailabilityPickerItem : TabItem + private class RoomAvailabilityPickerItem : DisableableTabItem { private const float transition_duration = 200; @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Multi.Components public RoomAvailabilityPickerItem(RoomAvailability value) : base(value) { RelativeSizeAxes = Axes.Y; - Width = 120; + Width = 102; Masking = true; CornerRadius = 5; diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index f50eefe4c6..99afc437d0 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -125,6 +125,8 @@ namespace osu.Game.Screens.Multi.Components RelativeSizeAxes = Axes.X, TabbableContentContainer = this, OnCommit = (sender, text) => apply(), + Alpha = 0.2f, + ReadOnly = true, }, }, }, @@ -149,6 +151,21 @@ namespace osu.Game.Screens.Multi.Components typeBind.ValueChanged += t => TypePicker.Current.Value = t; maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); + AvailabilityPicker.DisabledItems = new[] + { + RoomAvailability.FriendsOnly, + RoomAvailability.InviteOnly + }; + + TypePicker.DisabledItems = new GameType[] + { + new GameTypeTag(), + new GameTypeVersus(), + new GameTypeTagTeam(), + new GameTypeTeamVersus(), + }; + + Room = new Room(); } From 1ca00f66628c25831b083271f20c99874b673541 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 17:13:22 +0900 Subject: [PATCH 047/355] Add registration API call and related error handling --- osu.Game/Online/API/APIAccess.cs | 32 ++++++++- osu.Game/Online/API/RegsitrationRequest.cs | 26 +++++-- .../AccountCreation/ErrorTextFlowContainer.cs | 35 +++++++++ osu.Game/Overlays/AccountCreationOverlay.cs | 71 +++++++++++++++---- 4 files changed, 142 insertions(+), 22 deletions(-) create mode 100644 osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 3c99290080..cf2aae753e 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -5,7 +5,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Net; +using System.Net.Http; using System.Threading; +using Newtonsoft.Json.Linq; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Logging; @@ -189,13 +191,37 @@ namespace osu.Game.Online.API this.password = password; } - public void CreateAccount(string email, string username, string password) + public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) { Debug.Assert(State == APIState.Offline); - var req = new RegistrationRequest(); + var req = new RegistrationRequest + { + Url = $@"{Endpoint}/users", + Method = HttpMethod.Post, + Username = username, + Email = email, + Password = password + }; - req.Perform(); + try + { + req.Perform(); + } + catch (Exception e) + { + try + { + return JObject.Parse(req.ResponseString).SelectToken("form_error", true).ToObject(); + } + catch + { + // if we couldn't deserialize the error message let's throw the original exception outwards. + throw e; + } + } + + return null; } /// diff --git a/osu.Game/Online/API/RegsitrationRequest.cs b/osu.Game/Online/API/RegsitrationRequest.cs index 134bf45263..f703927101 100644 --- a/osu.Game/Online/API/RegsitrationRequest.cs +++ b/osu.Game/Online/API/RegsitrationRequest.cs @@ -1,11 +1,12 @@ // 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.Framework.IO.Network; namespace osu.Game.Online.API { - internal class RegsitrationRequest : JsonWebRequest + public class RegistrationRequest : WebRequest { internal string Username; internal string Email; @@ -13,11 +14,28 @@ namespace osu.Game.Online.API protected override void PrePerform() { - AddParameter("user", Username); - AddParameter("user_email", Email); - AddParameter("password", Password); + AddParameter("user[username]", Username); + AddParameter("user[user_email]", Email); + AddParameter("user[password]", Password); base.PrePerform(); } + + public class RegistrationRequestErrors + { + public UserErrors User; + + public class UserErrors + { + [JsonProperty("username")] + public string[] Username; + + [JsonProperty("user_email")] + public string[] Email; + + [JsonProperty("password")] + public string[] Password; + } + } } } diff --git a/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs b/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs new file mode 100644 index 0000000000..9ff6a5a7ef --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs @@ -0,0 +1,35 @@ +// 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.Graphics; +using osu.Game.Graphics.Containers; +using osuTK.Graphics; + +namespace osu.Game.Overlays.AccountCreation +{ + public class ErrorTextFlowContainer : OsuTextFlowContainer + { + private readonly List errorDrawables = new List(); + + public ErrorTextFlowContainer() + : base(cp => { cp.TextSize = 12; }) + { + } + + public void ClearErrors() + { + errorDrawables.ForEach(d => d.Expire()); + } + + public void AddErrors(string[] errors) + { + ClearErrors(); + + if (errors == null) return; + + foreach (var error in errors) + errorDrawables.AddRange(AddParagraph(error, cp => cp.Colour = Color4.Red)); + } + } +} diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index b8d428a839..6be7ad031c 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.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; using System.Collections.Generic; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.IEnumerableExtensions; @@ -24,9 +26,9 @@ namespace osu.Game.Overlays { public class AccountCreationOverlay : OsuFocusedOverlayContainer, IOnlineComponent { - private OsuTextFlowContainer usernameDescription; - private OsuTextFlowContainer emailAddressDescription; - private OsuTextFlowContainer passwordDescription; + private ErrorTextFlowContainer usernameDescription; + private ErrorTextFlowContainer emailAddressDescription; + private ErrorTextFlowContainer passwordDescription; private OsuTextBox usernameTextBox; private OsuTextBox emailTextBox; @@ -43,8 +45,6 @@ namespace osu.Game.Overlays Size = new Vector2(620, 450); Anchor = Anchor.Centre; Origin = Anchor.Centre; - - State = Visibility.Visible; } [BackgroundDependencyLoader] @@ -114,9 +114,10 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, TabbableContentContainer = this }, - usernameDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + usernameDescription = new ErrorTextFlowContainer { - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y }, emailTextBox = new OsuTextBox { @@ -125,9 +126,10 @@ namespace osu.Game.Overlays Text = api.ProvidedUsername ?? string.Empty, TabbableContentContainer = this }, - emailAddressDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + emailAddressDescription = new ErrorTextFlowContainer { - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y }, passwordTextBox = new OsuPasswordTextBox { @@ -135,9 +137,10 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, TabbableContentContainer = this, }, - passwordDescription = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + passwordDescription = new ErrorTextFlowContainer { - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y }, new Container { @@ -175,9 +178,7 @@ namespace osu.Game.Overlays characterCheckText = passwordDescription.AddText("8 characters long"); passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); - passwordTextBox.Current.ValueChanged += text => { - characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); - }; + passwordTextBox.Current.ValueChanged += text => { characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; } private void performRegistration() @@ -191,7 +192,47 @@ namespace osu.Game.Overlays return; } - api.CreateAccount(emailTextBox.Text, usernameTextBox.Text, passwordTextBox.Text); + usernameDescription.ClearErrors(); + emailAddressDescription.ClearErrors(); + passwordDescription.ClearErrors(); + + Task.Run(() => + { + bool success; + RegistrationRequest.RegistrationRequestErrors errors = null; + + try + { + errors = api.CreateAccount(emailTextBox.Text, usernameTextBox.Text, passwordTextBox.Text); + success = errors == null; + } + catch (Exception) + { + success = false; + } + + Schedule(() => + { + if (!success) + { + if (errors != null) + { + usernameDescription.AddErrors(errors.User.Username); + emailAddressDescription.AddErrors(errors.User.Email); + passwordDescription.AddErrors(errors.User.Password); + } + else + { + passwordDescription.AddErrors(new[] { "Something happened... but we're not sure what." }); + } + + registerShake.Shake(); + return; + } + + api.Login(emailTextBox.Text, passwordTextBox.Text); + }); + }); } private OsuTextBox nextUnfilledTextbox() From 4f46fa4798d81464f26f20bce7da38c6ed2561e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 17:30:16 +0900 Subject: [PATCH 048/355] Hide on connect --- osu.Game/Overlays/AccountCreationOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index 6be7ad031c..ba54538d61 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -268,6 +268,7 @@ namespace osu.Game.Overlays case APIState.Connecting: break; case APIState.Online: + State = Visibility.Hidden; break; } } From 6d7e71c003f6efb9fc79e740d9723b115f819d2a Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Wed, 5 Dec 2018 16:28:36 +0700 Subject: [PATCH 049/355] Fix switch stetement order 2 --- .../Judgements/TaikoDrumRollTickJudgement.cs | 4 ++-- osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 0ccc66877c..c2675a7fac 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -13,10 +13,10 @@ namespace osu.Game.Rulesets.Taiko.Judgements { switch (result) { - default: - return 0; case HitResult.Great: return 200; + default: + return 0; } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index c3b603746b..bbdc14c6d4 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -37,14 +37,14 @@ namespace osu.Game.Rulesets.Taiko.Judgements { switch (result) { - default: - return 0; case HitResult.Miss: return -1.0; case HitResult.Good: return 1.1; case HitResult.Great: return 3.0; + default: + return 0; } } From 94045413ceae0f5d681e4c05070b212049eee235 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 19:44:01 +0900 Subject: [PATCH 050/355] Change statistics to be int for now --- osu.Game.Tests/Scores/IO/ImportScoreTest.cs | 2 +- osu.Game.Tests/Visual/TestCaseResults.cs | 2 +- .../Online/API/Requests/Responses/APIScoreInfo.cs | 2 +- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 12 ++++++------ osu.Game/Scoring/ScoreInfo.cs | 4 ++-- osu.Game/Screens/Ranking/ResultsPageScore.cs | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 66363deb7c..7ee7acd539 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -100,7 +100,7 @@ namespace osu.Game.Tests.Scores.IO var toImport = new ScoreInfo { - Statistics = new Dictionary + Statistics = new Dictionary { { HitResult.Perfect, 100 }, { HitResult.Miss, 50 } diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/TestCaseResults.cs index dfe1cdbfb0..6a20a808b6 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/TestCaseResults.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual MaxCombo = 123, Rank = ScoreRank.A, Date = DateTimeOffset.Now, - Statistics = new Dictionary + Statistics = new Dictionary { { HitResult.Great, 50 }, { HitResult.Good, 20 }, diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index 838c4f95e4..b26bc751b9 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -65,7 +65,7 @@ namespace osu.Game.Online.API.Requests.Responses } [JsonProperty(@"statistics")] - private Dictionary jsonStats + private Dictionary jsonStats { set { diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 13fe021f95..3184f776a7 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -116,12 +116,12 @@ namespace osu.Game.Scoring.Legacy 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]; + int countMiss = score.Statistics[HitResult.Miss]; + int count50 = score.Statistics[HitResult.Meh]; + int count100 = score.Statistics[HitResult.Good]; + int count300 = score.Statistics[HitResult.Great]; + int countGeki = score.Statistics[HitResult.Perfect]; + int countKatu = score.Statistics[HitResult.Ok]; switch (score.Ruleset.ID) { diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index e6bab194b0..fb894e621e 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -104,7 +104,7 @@ namespace osu.Game.Scoring public DateTimeOffset Date { get; set; } [JsonIgnore] - public Dictionary Statistics = new Dictionary(); + public Dictionary Statistics = new Dictionary(); [Column("Statistics")] public string StatisticsJson @@ -118,7 +118,7 @@ namespace osu.Game.Scoring return; } - Statistics = JsonConvert.DeserializeObject>(value); + Statistics = JsonConvert.DeserializeObject>(value); } } diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 153d154d40..62103314e1 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -196,9 +196,9 @@ namespace osu.Game.Screens.Ranking private class DrawableScoreStatistic : Container { - private readonly KeyValuePair statistic; + private readonly KeyValuePair statistic; - public DrawableScoreStatistic(KeyValuePair statistic) + public DrawableScoreStatistic(KeyValuePair statistic) { this.statistic = statistic; From 68745b221e8f707b16f02cd86f21d239e45ddb9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Dec 2018 19:46:07 +0900 Subject: [PATCH 051/355] Update projects to target .NET core 2.2 --- osu.Desktop/osu.Desktop.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 09bfdc67d4..6b5fe501a7 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp2.2 WinExe AnyCPU true diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index b76f591239..21afc4141d 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp2.1 + netcoreapp2.2 diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 98ad086c66..c835b01b1c 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp2.1 + netcoreapp2.2 diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 6117812f45..84086a7c4d 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp2.1 + netcoreapp2.2 diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 3ba64398f3..36caae39c8 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -9,7 +9,7 @@ WinExe - netcoreapp2.1 + netcoreapp2.2 diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index c0f0695ff8..5387f209e3 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -10,7 +10,7 @@ WinExe - netcoreapp2.1 + netcoreapp2.2 From 1a3c06f2d9bd86ea37789705e79e615045e3c66f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Dec 2018 20:19:21 +0900 Subject: [PATCH 052/355] Fix OsuTestCase beatmap not having a correct default beatmap --- osu.Game/Tests/Visual/OsuTestCase.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 67a13bd850..80c9b2ab47 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -29,6 +29,9 @@ namespace osu.Game.Tests.Visual { Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures + beatmap.Default = new DummyWorkingBeatmap(Dependencies.Get()); + Dependencies.CacheAs(beatmap); Dependencies.CacheAs(beatmap); From 5f0bde581c5ad5b07f5b601f5712363a29e489ae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Dec 2018 20:42:16 +0900 Subject: [PATCH 053/355] Fix OsuBindableBeatmap not being able to be auto-constructed --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 2729676504..28d5c557bc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -259,7 +259,7 @@ namespace osu.Game RegisterAudioManager(audioManager); } - private OsuBindableBeatmap(WorkingBeatmap defaultValue) + public OsuBindableBeatmap(WorkingBeatmap defaultValue) : base(defaultValue) { } From dbc33c45a63524b4c676215b18e9426d1b123f8d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 00:14:21 +0900 Subject: [PATCH 054/355] Update nuget packages --- osu.Desktop/osu.Desktop.csproj | 4 ++-- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 4 ++-- osu.Game/osu.Game.csproj | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 6b5fe501a7..ad08f57c3a 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -28,8 +28,8 @@ - - + + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 21afc4141d..e875af5a30 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index c835b01b1c..0c6fbfa7d3 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 84086a7c4d..35f137572d 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 36caae39c8..0fc01deed6 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 5387f209e3..6b751db9e6 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -2,10 +2,10 @@ - + - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 85eabb0350..30fb02b306 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,10 +14,10 @@ - + - - + + From 669a17529a49512d04ca7e461a860c1da745f9e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 11:55:58 +0900 Subject: [PATCH 055/355] Move external link opened to top most level --- osu.Game/OsuGame.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a5dd7ab071..e12723a61d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -402,16 +402,21 @@ namespace osu.Game Origin = Anchor.TopRight, }, overlayContent.Add); - loadComponentSingleFile(dialogOverlay = new DialogOverlay + loadComponentSingleFile(accountCreation = new AccountCreationOverlay { Depth = -6, }, overlayContent.Add); - loadComponentSingleFile(accountCreation = new AccountCreationOverlay + loadComponentSingleFile(dialogOverlay = new DialogOverlay { Depth = -7, }, overlayContent.Add); + loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener + { + Depth = -8, + }, overlayContent.Add); + dependencies.Cache(idleTracker); dependencies.Cache(settings); dependencies.Cache(onscreenDisplay); @@ -426,8 +431,6 @@ namespace osu.Game dependencies.Cache(dialogOverlay); dependencies.Cache(accountCreation); - Add(externalLinkOpener = new ExternalLinkOpener()); - var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications }; overlays.AddRange(singleDisplaySideOverlays); From 0df9fa1e5905f8c976459d31b806518c7d0a21f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 11:56:16 +0900 Subject: [PATCH 056/355] Remove pointless default size specification in OsuLogo --- osu.Game/Screens/Menu/OsuLogo.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index f858fded92..eafe44c0fc 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -79,8 +79,6 @@ namespace osu.Game.Screens.Menu private readonly Container impactContainer; - private const float default_size = 480; - private const double early_activation = 60; public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; @@ -89,8 +87,6 @@ namespace osu.Game.Screens.Menu { EarlyActivationMilliseconds = early_activation; - Size = new Vector2(default_size); - Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; From e56f4cc8a5056c5cbadb9b7a3cb4793d12908de0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 11:58:09 +0900 Subject: [PATCH 057/355] Add remaining steps to registration screen --- .../Visual/TestCaseAccountCreationOverlay.cs | 13 ++ ...ground.cs => AccountCreationBackground.cs} | 3 + .../AccountCreation/AccountCreationScreen.cs | 28 +++ .../Overlays/AccountCreation/ScreenEntry.cs | 202 ++++++++++++++++++ .../Overlays/AccountCreation/ScreenWarning.cs | 95 ++++++++ .../Overlays/AccountCreation/ScreenWelcome.cs | 63 ++++++ osu.Game/Overlays/AccountCreationOverlay.cs | 177 +-------------- 7 files changed, 407 insertions(+), 174 deletions(-) rename osu.Game/Overlays/AccountCreation/{RegistrationBackground.cs => AccountCreationBackground.cs} (89%) create mode 100644 osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs create mode 100644 osu.Game/Overlays/AccountCreation/ScreenEntry.cs create mode 100644 osu.Game/Overlays/AccountCreation/ScreenWarning.cs create mode 100644 osu.Game/Overlays/AccountCreation/ScreenWelcome.cs diff --git a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs index c8ee86e5fd..c54ac448dd 100644 --- a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs @@ -1,13 +1,26 @@ // 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 osu.Framework.Graphics.Containers; using osu.Game.Overlays; +using osu.Game.Overlays.AccountCreation; namespace osu.Game.Tests.Visual { public class TestCaseAccountCreationOverlay : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ErrorTextFlowContainer), + typeof(AccountCreationBackground), + typeof(ScreenEntry), + typeof(ScreenWarning), + typeof(ScreenWelcome), + typeof(AccountCreationScreen), + }; + public TestCaseAccountCreationOverlay() { var accountCreation = new AccountCreationOverlay(); diff --git a/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs similarity index 89% rename from osu.Game/Overlays/AccountCreation/RegistrationBackground.cs rename to osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs index 45c495d142..d1686912c5 100644 --- a/osu.Game/Overlays/AccountCreation/RegistrationBackground.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs new file mode 100644 index 0000000000..134db37afa --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Screens; + +namespace osu.Game.Overlays.AccountCreation +{ + public abstract class AccountCreationScreen : Screen + { + protected AccountCreationScreen() + { + ValidForResume = false; + } + + protected override void OnEntering(Screen last) + { + base.OnEntering(last); + Content.FadeOut().Delay(200).FadeIn(200); + } + + protected override void OnSuspending(Screen next) + { + base.OnSuspending(next); + Content.FadeOut(200); + } + } +} diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs new file mode 100644 index 0000000000..141e39be8f --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -0,0 +1,202 @@ +// 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.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.MathUtils; +using osu.Framework.Screens; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays.Settings; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.AccountCreation +{ + public class ScreenEntry : AccountCreationScreen + { + private ErrorTextFlowContainer usernameDescription; + private ErrorTextFlowContainer emailAddressDescription; + private ErrorTextFlowContainer passwordDescription; + + private OsuTextBox usernameTextBox; + private OsuTextBox emailTextBox; + private OsuPasswordTextBox passwordTextBox; + + private APIAccess api; + private ShakeContainer registerShake; + private IEnumerable characterCheckText; + + protected override void OnEntering(Screen last) + { + base.OnEntering(last); + + var nextTextbox = nextUnfilledTextbox(); + if (nextTextbox != null) + Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, APIAccess api) + { + this.api = api; + + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + TextSize = 20, + Margin = new MarginPadding { Vertical = 10 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Let's create an account!", + }, + usernameTextBox = new OsuTextBox + { + PlaceholderText = "username", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + usernameDescription = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + emailTextBox = new OsuTextBox + { + PlaceholderText = "email address", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + emailAddressDescription = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + passwordTextBox = new OsuPasswordTextBox + { + PlaceholderText = "password", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + passwordDescription = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + registerShake = new ShakeContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new SettingsButton + { + Text = "Register", + Margin = new MarginPadding { Vertical = 20 }, + Action = performRegistration + } + } + } + }, + } + }; + + usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); + + emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); + emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = "Exo2.0-Bold"); + + passwordDescription.AddText("At least "); + characterCheckText = passwordDescription.AddText("8 characters long"); + passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); + + passwordTextBox.Current.ValueChanged += text => { characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; + } + + private void performRegistration() + { + var textbox = nextUnfilledTextbox(); + + if (textbox != null) + { + Schedule(() => GetContainingInputManager().ChangeFocus(textbox)); + registerShake.Shake(); + return; + } + + usernameDescription.ClearErrors(); + emailAddressDescription.ClearErrors(); + passwordDescription.ClearErrors(); + + Task.Run(() => + { + bool success; + RegistrationRequest.RegistrationRequestErrors errors = null; + + try + { + errors = api.CreateAccount(emailTextBox.Text, usernameTextBox.Text, passwordTextBox.Text); + success = errors == null; + } + catch (Exception) + { + success = false; + } + + Schedule(() => + { + if (!success) + { + if (errors != null) + { + usernameDescription.AddErrors(errors.User.Username); + emailAddressDescription.AddErrors(errors.User.Email); + passwordDescription.AddErrors(errors.User.Password); + } + else + { + passwordDescription.AddErrors(new[] { "Something happened... but we're not sure what." }); + } + + registerShake.Shake(); + return; + } + + api.Login(emailTextBox.Text, passwordTextBox.Text); + }); + }); + } + + private OsuTextBox nextUnfilledTextbox() + { + OsuTextBox textboxIfUsable(OsuTextBox textbox) + { + return !string.IsNullOrEmpty(textbox.Text) ? null : textbox; + } + + return textboxIfUsable(usernameTextBox) ?? textboxIfUsable(emailTextBox) ?? textboxIfUsable(passwordTextBox); + } + } +} diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs new file mode 100644 index 0000000000..6f887e23a2 --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -0,0 +1,95 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API; +using osu.Game.Overlays.Settings; +using osu.Game.Screens.Menu; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.AccountCreation +{ + public class ScreenWarning : AccountCreationScreen + { + private OsuTextFlowContainer multiAccountExplanationText; + private LinkFlowContainer furtherAssistance; + + private const string help_centre_url = "https://osu.ppy.sh/help/wiki/Help_Centre#login"; + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, APIAccess api, OsuGame game) + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + new OsuLogo + { + Scale = new Vector2(0.1f), + Margin = new MarginPadding { Top = 500, Bottom = 300 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Triangles = false, + BeatMatching = false, + }, + new OsuSpriteText + { + TextSize = 28, + Font = "Exo2.0-Light", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = Color4.Red, + Text = "Warning! 注意!", + }, + multiAccountExplanationText = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + new SettingsButton + { + Text = "Help, I can't access my account!", + Margin = new MarginPadding { Top = 50 }, + Action = () => game?.OpenUrlExternally(help_centre_url) + }, + new DangerousSettingsButton + { + Text = "I understand. This account isn't for me.", + Action = () => Push(new ScreenEntry()) + }, + furtherAssistance = new LinkFlowContainer(cp => { cp.TextSize = 12; }) + { + Margin = new MarginPadding { Top = 20 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both + }, + } + }; + + multiAccountExplanationText.AddText("Are you "); + multiAccountExplanationText.AddText(api.ProvidedUsername, cp => cp.Colour = colours.BlueLight); + multiAccountExplanationText.AddText("? osu! has a policy of "); + multiAccountExplanationText.AddText("one account per person!", cp => cp.Colour = colours.Yellow); + multiAccountExplanationText.AddText(" Please be aware that creating more than one account per person may result in "); + multiAccountExplanationText.AddText("permanent deactivation of accounts", cp => cp.Colour = colours.Yellow); + multiAccountExplanationText.AddText("."); + + furtherAssistance.AddText("Need further assistance? Contact us via our "); + furtherAssistance.AddLink("support system", help_centre_url); + furtherAssistance.AddText("."); + } + } +} diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs new file mode 100644 index 0000000000..0a4b35342e --- /dev/null +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Settings; +using osu.Game.Screens.Menu; +using osuTK; + +namespace osu.Game.Overlays.AccountCreation +{ + public class ScreenWelcome : AccountCreationScreen + { + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + new OsuLogo + { + Scale = new Vector2(0.1f), + Margin = new MarginPadding { Vertical = 500 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Triangles = false, + BeatMatching = false, + }, + new OsuSpriteText + { + TextSize = 24, + Font = "Exo2.0-Light", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "New Player Registration", + }, + new OsuSpriteText + { + TextSize = 12, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "let's get you started", + }, + new SettingsButton + { + Text = "Let's create an account!", + Margin = new MarginPadding { Vertical = 120 }, + Action = () => Push(new ScreenWarning()) + } + } + }; + } + } +} diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index ba54538d61..9f3470de21 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -1,43 +1,22 @@ // 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.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osuTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays.AccountCreation; -using osu.Game.Overlays.Settings; using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays { public class AccountCreationOverlay : OsuFocusedOverlayContainer, IOnlineComponent { - private ErrorTextFlowContainer usernameDescription; - private ErrorTextFlowContainer emailAddressDescription; - private ErrorTextFlowContainer passwordDescription; - - private OsuTextBox usernameTextBox; - private OsuTextBox emailTextBox; - private OsuPasswordTextBox passwordTextBox; - - private APIAccess api; - private ShakeContainer registerShake; - private IEnumerable characterCheckText; - private const float transition_time = 400; public AccountCreationOverlay() @@ -50,8 +29,6 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(OsuColour colours, APIAccess api) { - this.api = api; - api.Register(this); Children = new Drawable[] @@ -90,166 +67,18 @@ namespace osu.Game.Overlays Colour = Color4.Black, Alpha = 0.9f, }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Padding = new MarginPadding(20), - Spacing = new Vector2(0, 10), - Children = new Drawable[] - { - new OsuSpriteText - { - TextSize = 20, - Margin = new MarginPadding { Vertical = 10 }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "Let's create an account!", - }, - usernameTextBox = new OsuTextBox - { - PlaceholderText = "username", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this - }, - usernameDescription = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - emailTextBox = new OsuTextBox - { - PlaceholderText = "email address", - RelativeSizeAxes = Axes.X, - Text = api.ProvidedUsername ?? string.Empty, - TabbableContentContainer = this - }, - emailAddressDescription = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - passwordTextBox = new OsuPasswordTextBox - { - PlaceholderText = "password", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - }, - passwordDescription = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - registerShake = new ShakeContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = new SettingsButton - { - Text = "Register", - Margin = new MarginPadding { Vertical = 20 }, - Action = performRegistration - } - } - } - }, - } - }, + new ScreenWelcome(), } } } } }; - - usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); - - emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); - emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = "Exo2.0-Bold"); - - passwordDescription.AddText("At least "); - characterCheckText = passwordDescription.AddText("8 characters long"); - passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); - - passwordTextBox.Current.ValueChanged += text => { characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; - } - - private void performRegistration() - { - var textbox = nextUnfilledTextbox(); - - if (textbox != null) - { - Schedule(() => GetContainingInputManager().ChangeFocus(textbox)); - registerShake.Shake(); - return; - } - - usernameDescription.ClearErrors(); - emailAddressDescription.ClearErrors(); - passwordDescription.ClearErrors(); - - Task.Run(() => - { - bool success; - RegistrationRequest.RegistrationRequestErrors errors = null; - - try - { - errors = api.CreateAccount(emailTextBox.Text, usernameTextBox.Text, passwordTextBox.Text); - success = errors == null; - } - catch (Exception) - { - success = false; - } - - Schedule(() => - { - if (!success) - { - if (errors != null) - { - usernameDescription.AddErrors(errors.User.Username); - emailAddressDescription.AddErrors(errors.User.Email); - passwordDescription.AddErrors(errors.User.Password); - } - else - { - passwordDescription.AddErrors(new[] { "Something happened... but we're not sure what." }); - } - - registerShake.Shake(); - return; - } - - api.Login(emailTextBox.Text, passwordTextBox.Text); - }); - }); - } - - private OsuTextBox nextUnfilledTextbox() - { - OsuTextBox textboxIfUsable(OsuTextBox textbox) => !string.IsNullOrEmpty(textbox.Text) ? null : textbox; - - return textboxIfUsable(usernameTextBox) ?? textboxIfUsable(emailTextBox) ?? textboxIfUsable(passwordTextBox); } protected override void PopIn() { base.PopIn(); this.FadeIn(transition_time, Easing.OutQuint); - - var nextTextbox = nextUnfilledTextbox(); - if (nextTextbox != null) - Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); } protected override void PopOut() From 966c2f65475e9149f3a65ca53566fde63b3e04de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 12:05:13 +0900 Subject: [PATCH 058/355] Update resources --- osu-resources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-resources b/osu-resources index 694cb03f19..b622fe6d70 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 694cb03f19c93106ed0f2593f3e506e835fb652a +Subproject commit b622fe6d700d3b8e4602ff6b7e5f8b516825aea5 From d3f5111fa108e2e1db762577be3a372d7e806d6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 12:17:08 +0900 Subject: [PATCH 059/355] Use relative URL --- osu.Game/OsuGame.cs | 8 +++++++- osu.Game/OsuGameBase.cs | 12 +++++++----- osu.Game/Overlays/AccountCreation/ScreenWarning.cs | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e12723a61d..15f011e122 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -187,7 +187,13 @@ namespace osu.Game } private ExternalLinkOpener externalLinkOpener; - public void OpenUrlExternally(string url) => externalLinkOpener.OpenUrlExternally(url); + public void OpenUrlExternally(string url) + { + if (url.StartsWith("/")) + url = $"{API.Endpoint}{url}"; + + externalLinkOpener.OpenUrlExternally(url); + } private ScheduledDelegate scoreLoad; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 2729676504..0f1819d55b 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -60,6 +60,8 @@ namespace osu.Game protected RulesetConfigCache RulesetConfigCache; + protected APIAccess API; + protected MenuCursorContainer MenuCursorContainer; private Container content; @@ -146,14 +148,14 @@ namespace osu.Game dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); dependencies.CacheAs(SkinManager); - var api = new APIAccess(LocalConfig); + API = new APIAccess(LocalConfig); - dependencies.Cache(api); - dependencies.CacheAs(api); + dependencies.Cache(API); + dependencies.CacheAs(API); 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(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host)); dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, BeatmapManager, Host.Storage, contextFactory, Host)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); @@ -177,7 +179,7 @@ namespace osu.Game FileStore.Cleanup(); - AddInternal(api); + AddInternal(API); GlobalActionContainer globalBinding; diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 6f887e23a2..c1d5332ca7 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.AccountCreation private OsuTextFlowContainer multiAccountExplanationText; private LinkFlowContainer furtherAssistance; - private const string help_centre_url = "https://osu.ppy.sh/help/wiki/Help_Centre#login"; + private const string help_centre_url = "/help/wiki/Help_Centre#login"; [BackgroundDependencyLoader(true)] private void load(OsuColour colours, APIAccess api, OsuGame game) From eadbe4c4709a8730c01730a87c51cdf2f492da70 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Dec 2018 12:21:30 +0900 Subject: [PATCH 060/355] Make beatmap selection work --- osu.Game.Tests/Visual/TestCaseMatchHeader.cs | 43 ---------------- .../UpdateableBeatmapBackgroundSprite.cs | 50 +++++++++++++++++++ .../Screens/Multi/Components/DrawableRoom.cs | 22 +++++--- .../Screens/Multi/Components/RoomInspector.cs | 28 ++++++----- .../Screens/Multi/Screens/Match/Header.cs | 15 +++--- osu.Game/Screens/Multi/Screens/Match/Match.cs | 24 ++++++--- 6 files changed, 106 insertions(+), 76 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseMatchHeader.cs create mode 100644 osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs deleted file mode 100644 index 34f98f97c2..0000000000 --- a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Game.Beatmaps; -using osu.Game.Screens.Multi.Screens.Match; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseMatchHeader : OsuTestCase - { - public TestCaseMatchHeader() - { - Header header = new Header(); - Add(header); - - AddStep(@"set beatmap set", () => header.BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/760757/covers/cover.jpg?1526944540", - }, - }, - }); - - AddStep(@"change beatmap set", () => header.BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/761883/covers/cover.jpg?1525557400", - }, - }, - }); - - AddStep(@"null beatmap set", () => header.BeatmapSet = null); - } - } -} diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs new file mode 100644 index 0000000000..5ced21e436 --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Beatmaps.Drawables +{ + public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable + { + public readonly IBindable Beatmap = new Bindable(); + + [Resolved] + private OsuGameBase game { get; set; } + + public UpdateableBeatmapBackgroundSprite() + { + Beatmap.BindValueChanged(b => Schedule(() => Model = b)); + } + + protected override Drawable CreateDrawable(WorkingBeatmap model) + { + Drawable drawable = model == null ? (Drawable)new DefaultSprite() : new BeatmapBackgroundSprite(model); + + drawable.RelativeSizeAxes = Axes.Both; + drawable.Anchor = Anchor.Centre; + drawable.Origin = Anchor.Centre; + drawable.FillMode = FillMode.Fill; + + return drawable; + } + + protected override double FadeDuration => 400; + + private class DefaultSprite : Sprite + { + [Resolved] + private IBindableBeatmap gameBeatmap { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + Texture = gameBeatmap.Default.Background; + } + } + } +} diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 2f26f53e8b..30bee7829e 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -44,9 +44,14 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); + private readonly Bindable roomBeatmap = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly Bindable beatmap = new Bindable(); + + [Resolved] + private BeatmapManager beatmaps { get; set; } + public readonly Room Room; private SelectionState state; @@ -101,7 +106,7 @@ namespace osu.Game.Screens.Multi.Components private void load(OsuColour colours) { Box sideStrip; - UpdateableBeatmapSetCover cover; + UpdateableBeatmapBackgroundSprite background; OsuSpriteText name, status; ParticipantInfo participantInfo; BeatmapTitle beatmapTitle; @@ -137,12 +142,13 @@ namespace osu.Game.Screens.Multi.Components RelativeSizeAxes = Axes.Y, Width = side_strip_width, }, - cover = new UpdateableBeatmapSetCover + new Container { - Width = cover_width, RelativeSizeAxes = Axes.Y, + Width = cover_width, Masking = true, Margin = new MarginPadding { Left = side_strip_width }, + Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } }, new Container { @@ -216,9 +222,11 @@ namespace osu.Game.Screens.Multi.Components d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }; - beatmapBind.ValueChanged += b => + background.Beatmap.BindTo(beatmap); + + roomBeatmap.ValueChanged += b => { - cover.BeatmapSet = b?.BeatmapSet; + beatmap.Value = beatmaps.GetWorkingBeatmap(b); beatmapTitle.Beatmap = b; modeTypeInfo.Beatmap = b; }; @@ -227,7 +235,7 @@ namespace osu.Game.Screens.Multi.Components hostBind.BindTo(Room.Host); statusBind.BindTo(Room.Status); typeBind.BindTo(Room.Type); - beatmapBind.BindTo(Room.Beatmap); + roomBeatmap.BindTo(Room.Beatmap); participantsBind.BindTo(Room.Participants); } diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index 1ec509d5a8..b7dcb3c8fb 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -32,13 +32,15 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); + private readonly Bindable roomBeatmap = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly Bindable beatmap = new Bindable(); + private OsuColour colours; private Box statusStrip; - private UpdateableBeatmapSetCover cover; + private UpdateableBeatmapBackgroundSprite background; private ParticipantCount participantCount; private FillFlowContainer topFlow, participantsFlow; private OsuSpriteText name, status; @@ -46,6 +48,9 @@ namespace osu.Game.Screens.Multi.Components private ScrollContainer participantsScroll; private ParticipantInfo participantInfo; + [Resolved] + private BeatmapManager beatmaps { get; set; } + private Room room; public Room Room { @@ -59,7 +64,7 @@ namespace osu.Game.Screens.Multi.Components hostBind.UnbindBindings(); statusBind.UnbindBindings(); typeBind.UnbindBindings(); - beatmapBind.UnbindBindings(); + roomBeatmap.UnbindBindings(); maxParticipantsBind.UnbindBindings(); participantsBind.UnbindBindings(); @@ -69,7 +74,7 @@ namespace osu.Game.Screens.Multi.Components hostBind.BindTo(room.Host); statusBind.BindTo(room.Status); typeBind.BindTo(room.Type); - beatmapBind.BindTo(room.Beatmap); + roomBeatmap.BindTo(room.Beatmap); maxParticipantsBind.BindTo(room.MaxParticipants); participantsBind.BindTo(room.Participants); } @@ -104,10 +109,7 @@ namespace osu.Game.Screens.Multi.Components Masking = true, Children = new Drawable[] { - cover = new UpdateableBeatmapSetCover - { - RelativeSizeAxes = Axes.Both, - }, + background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, new Box { RelativeSizeAxes = Axes.Both, @@ -207,9 +209,11 @@ namespace osu.Game.Screens.Multi.Components maxParticipantsBind.ValueChanged += m => participantCount.Max = m; statusBind.ValueChanged += displayStatus; - beatmapBind.ValueChanged += b => + background.Beatmap.BindTo(beatmap); + + roomBeatmap.ValueChanged += b => { - cover.BeatmapSet = b?.BeatmapSet; + beatmap.Value = beatmaps.GetWorkingBeatmap(b); beatmapTypeInfo.Beatmap = b; }; @@ -243,7 +247,7 @@ namespace osu.Game.Screens.Multi.Components { if (Room == null) { - cover.BeatmapSet = null; + beatmap.Value = null; participantsFlow.FadeOut(transition_duration); participantCount.FadeOut(transition_duration); beatmapTypeInfo.FadeOut(transition_duration); @@ -261,7 +265,7 @@ namespace osu.Game.Screens.Multi.Components participantInfo.FadeIn(transition_duration); statusBind.TriggerChange(); - beatmapBind.TriggerChange(); + roomBeatmap.TriggerChange(); } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index c2de50fa65..e4a7baf035 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -24,16 +25,12 @@ namespace osu.Game.Screens.Multi.Screens.Match { public const float HEIGHT = 200; + public readonly IBindable Beatmap = new Bindable(); + private readonly Box tabStrip; - private readonly UpdateableBeatmapSetCover cover; public readonly PageTabControl Tabs; - public BeatmapSetInfo BeatmapSet - { - set => cover.BeatmapSet = value; - } - public Action OnRequestSelectBeatmap; public Header() @@ -42,12 +39,14 @@ namespace osu.Game.Screens.Multi.Screens.Match Height = HEIGHT; BeatmapSelectButton beatmapButton; + UpdateableBeatmapBackgroundSprite background; Children = new Drawable[] { - cover = new UpdateableBeatmapSetCover + new Container { RelativeSizeAxes = Axes.Both, Masking = true, + Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } }, new Box { @@ -90,6 +89,8 @@ namespace osu.Game.Screens.Multi.Screens.Match }; beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); + + background.Beatmap.BindTo(Beatmap); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 2dbe0a9c3a..468390b75b 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,19 +23,24 @@ namespace osu.Game.Screens.Multi.Screens.Match private readonly Bindable statusBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly Bindable roomBeatmap = new Bindable(); + protected override Container TransitionContent => participants; public override string Title => room.Name.Value; public override string ShortTitle => "room"; + [Resolved] + private BeatmapManager beatmapManager { get; set; } + public Match(Room room) { this.room = room; + Header header; RoomSettingsOverlay settings; Info info; @@ -68,13 +74,9 @@ namespace osu.Game.Screens.Multi.Screens.Match }; header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect()); + header.Beatmap.BindTo(Beatmap); - beatmapBind.BindTo(room.Beatmap); - beatmapBind.BindValueChanged(b => - { - header.BeatmapSet = b?.BeatmapSet; - info.Beatmap = b; - }, true); + roomBeatmap.BindValueChanged(b => info.Beatmap = b, true); header.Tabs.Current.ValueChanged += t => { @@ -110,5 +112,13 @@ namespace osu.Game.Screens.Multi.Screens.Match participantsBind.BindTo(room.Participants); participantsBind.BindValueChanged(p => participants.Users = p, true); } + + [BackgroundDependencyLoader] + private void load() + { + roomBeatmap.BindTo(room.Beatmap); + roomBeatmap.BindValueChanged(b => Beatmap.Value = beatmapManager.GetWorkingBeatmap(room.Beatmap.Value), true); + Beatmap.BindValueChanged(b => roomBeatmap.Value = b.BeatmapInfo); + } } } From 88052dcea1d2dc1e947e8d72c8812e05128c5cfe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 12:38:11 +0900 Subject: [PATCH 061/355] Reset to welcome screen on exiting mid-process --- .../Overlays/AccountCreation/AccountCreationScreen.cs | 11 ++++++----- osu.Game/Overlays/AccountCreationOverlay.cs | 7 ++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs index 134db37afa..371428d988 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs @@ -8,17 +8,18 @@ namespace osu.Game.Overlays.AccountCreation { public abstract class AccountCreationScreen : Screen { - protected AccountCreationScreen() - { - ValidForResume = false; - } - protected override void OnEntering(Screen last) { base.OnEntering(last); Content.FadeOut().Delay(200).FadeIn(200); } + protected override void OnResuming(Screen last) + { + base.OnResuming(last); + Content.FadeIn(200); + } + protected override void OnSuspending(Screen next) { base.OnSuspending(next); diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index 9f3470de21..9bc4119716 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -19,6 +19,8 @@ namespace osu.Game.Overlays { private const float transition_time = 400; + private ScreenWelcome welcomeScreen; + public AccountCreationOverlay() { Size = new Vector2(620, 450); @@ -67,7 +69,7 @@ namespace osu.Game.Overlays Colour = Color4.Black, Alpha = 0.9f, }, - new ScreenWelcome(), + welcomeScreen = new ScreenWelcome(), } } } @@ -79,6 +81,9 @@ namespace osu.Game.Overlays { base.PopIn(); this.FadeIn(transition_time, Easing.OutQuint); + + if (welcomeScreen.ChildScreen != null) + welcomeScreen.MakeCurrent(); } protected override void PopOut() From cc3ccc4c40735fb08b46a549fe3d256a1ea60877 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 12:53:35 +0900 Subject: [PATCH 062/355] Affix logo in place better --- .../Overlays/AccountCreation/ScreenWarning.cs | 16 +++++++++------- .../Overlays/AccountCreation/ScreenWelcome.cs | 16 +++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index c1d5332ca7..6bc22d29c4 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -35,14 +35,16 @@ namespace osu.Game.Overlays.AccountCreation Spacing = new Vector2(0, 5), Children = new Drawable[] { - new OsuLogo + new Container { - Scale = new Vector2(0.1f), - Margin = new MarginPadding { Top = 500, Bottom = 300 }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Triangles = false, - BeatMatching = false, + RelativeSizeAxes = Axes.X, + Height = 150, + Child = new OsuLogo + { + Scale = new Vector2(0.1f), + Anchor = Anchor.Centre, + Triangles = false, + }, }, new OsuSpriteText { diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index 0a4b35342e..5b7dc21be8 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -26,14 +26,16 @@ namespace osu.Game.Overlays.AccountCreation Spacing = new Vector2(0, 5), Children = new Drawable[] { - new OsuLogo + new Container { - Scale = new Vector2(0.1f), - Margin = new MarginPadding { Vertical = 500 }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Triangles = false, - BeatMatching = false, + RelativeSizeAxes = Axes.X, + Height = 150, + Child = new OsuLogo + { + Scale = new Vector2(0.1f), + Anchor = Anchor.Centre, + Triangles = false, + }, }, new OsuSpriteText { From d5de5d1cb7063198e8c8b68ef2eac791242b24ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 14:57:00 +0900 Subject: [PATCH 063/355] Fix textbox focus issues --- .../Overlays/AccountCreation/ScreenEntry.cs | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 141e39be8f..7328372db2 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; @@ -10,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; -using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -36,14 +36,7 @@ namespace osu.Game.Overlays.AccountCreation private ShakeContainer registerShake; private IEnumerable characterCheckText; - protected override void OnEntering(Screen last) - { - base.OnEntering(last); - - var nextTextbox = nextUnfilledTextbox(); - if (nextTextbox != null) - Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); - } + private OsuTextBox[] textboxes; [BackgroundDependencyLoader] private void load(OsuColour colours, APIAccess api) @@ -123,6 +116,8 @@ namespace osu.Game.Overlays.AccountCreation } }; + textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox }; + usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); @@ -135,13 +130,18 @@ namespace osu.Game.Overlays.AccountCreation passwordTextBox.Current.ValueChanged += text => { characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; } + protected override void Update() + { + base.Update(); + + if (!textboxes.Any(t => t.HasFocus)) + focusNextTextbox(); + } + private void performRegistration() { - var textbox = nextUnfilledTextbox(); - - if (textbox != null) + if (focusNextTextbox()) { - Schedule(() => GetContainingInputManager().ChangeFocus(textbox)); registerShake.Shake(); return; } @@ -189,14 +189,18 @@ namespace osu.Game.Overlays.AccountCreation }); } - private OsuTextBox nextUnfilledTextbox() + private bool focusNextTextbox() { - OsuTextBox textboxIfUsable(OsuTextBox textbox) + var nextTextbox = nextUnfilledTextbox(); + if (nextTextbox != null) { - return !string.IsNullOrEmpty(textbox.Text) ? null : textbox; + Schedule(() => GetContainingInputManager().ChangeFocus(nextTextbox)); + return true; } - return textboxIfUsable(usernameTextBox) ?? textboxIfUsable(emailTextBox) ?? textboxIfUsable(passwordTextBox); + return false; } + + private OsuTextBox nextUnfilledTextbox() => textboxes.FirstOrDefault(t => string.IsNullOrEmpty(t.Text)); } } From 67a759122acf0bba9b11dab0346ff1780e051b4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 14:59:17 +0900 Subject: [PATCH 064/355] Fix update code crashing when no internet connection is available --- osu.Desktop/Updater/SimpleUpdateManager.cs | 38 +++++++++++++--------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs index 6c363422f7..e404ccd2b3 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Desktop/Updater/SimpleUpdateManager.cs @@ -41,24 +41,32 @@ namespace osu.Desktop.Updater private async void checkForUpdateAsync() { - var releases = new JsonWebRequest("https://api.github.com/repos/ppy/osu/releases/latest"); - await releases.PerformAsync(); - - var latest = releases.ResponseObject; - - if (latest.TagName != version) + try { - notificationOverlay.Post(new SimpleNotification + var releases = new JsonWebRequest("https://api.github.com/repos/ppy/osu/releases/latest"); + + await releases.PerformAsync(); + + var latest = releases.ResponseObject; + + if (latest.TagName != version) { - Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" - + "Click here to download the new version, which can be installed over the top of your existing installation", - Icon = FontAwesome.fa_upload, - Activated = () => + notificationOverlay.Post(new SimpleNotification { - host.OpenUrlExternally(getBestUrl(latest)); - return true; - } - }); + Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" + + "Click here to download the new version, which can be installed over the top of your existing installation", + Icon = FontAwesome.fa_upload, + Activated = () => + { + host.OpenUrlExternally(getBestUrl(latest)); + return true; + } + }); + } + } + catch + { + // we shouldn't crash on a web failure. or any failure for the matter. } } From 09f985c721709a8b723ee22ca892f80f87111a4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 15:49:06 +0900 Subject: [PATCH 065/355] Add warning lines --- .../Overlays/AccountCreation/ScreenWarning.cs | 115 ++++++++++-------- 1 file changed, 66 insertions(+), 49 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 6bc22d29c4..9511f2f40c 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -4,6 +4,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -23,61 +25,76 @@ namespace osu.Game.Overlays.AccountCreation private const string help_centre_url = "/help/wiki/Help_Centre#login"; [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, APIAccess api, OsuGame game) + private void load(OsuColour colours, APIAccess api, OsuGame game, TextureStore textures) { - Child = new FillFlowContainer + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Padding = new MarginPadding(20), - Spacing = new Vector2(0, 5), - Children = new Drawable[] + new Sprite { - new Container + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Texture = textures.Get(@"Menu/dev-build-footer"), + }, + new Sprite + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Texture = textures.Get(@"Menu/dev-build-footer"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 5), + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 150, - Child = new OsuLogo + new Container { - Scale = new Vector2(0.1f), - Anchor = Anchor.Centre, - Triangles = false, + RelativeSizeAxes = Axes.X, + Height = 150, + Child = new OsuLogo + { + Scale = new Vector2(0.1f), + Anchor = Anchor.Centre, + Triangles = false, + }, }, - }, - new OsuSpriteText - { - TextSize = 28, - Font = "Exo2.0-Light", - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Colour = Color4.Red, - Text = "Warning! 注意!", - }, - multiAccountExplanationText = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - new SettingsButton - { - Text = "Help, I can't access my account!", - Margin = new MarginPadding { Top = 50 }, - Action = () => game?.OpenUrlExternally(help_centre_url) - }, - new DangerousSettingsButton - { - Text = "I understand. This account isn't for me.", - Action = () => Push(new ScreenEntry()) - }, - furtherAssistance = new LinkFlowContainer(cp => { cp.TextSize = 12; }) - { - Margin = new MarginPadding { Top = 20 }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both - }, + new OsuSpriteText + { + TextSize = 28, + Font = "Exo2.0-Light", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = Color4.Red, + Text = "Warning! 注意!", + }, + multiAccountExplanationText = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + new SettingsButton + { + Text = "Help, I can't access my account!", + Margin = new MarginPadding { Top = 50 }, + Action = () => game?.OpenUrlExternally(help_centre_url) + }, + new DangerousSettingsButton + { + Text = "I understand. This account isn't for me.", + Action = () => Push(new ScreenEntry()) + }, + furtherAssistance = new LinkFlowContainer(cp => { cp.TextSize = 12; }) + { + Margin = new MarginPadding { Top = 20 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both + }, + } } }; From b5277de3f4e5dfeb16bb7806b9a3c6b2350ad58a Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 14:08:32 +0700 Subject: [PATCH 066/355] Remove extra newline --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 40e7f3e12e..84f87bf10c 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -40,7 +40,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// private const double hp_miss_max = -0.012; - /// /// The HP awarded for a hit. /// From de8c5a6df0b441b6d6e1d8f2cab5d3e0684d5022 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 16:29:41 +0900 Subject: [PATCH 067/355] Block input and show loading when submitting registration --- .../UserInterface/LoadingAnimation.cs | 3 + .../UserInterface/ProcessingOverlay.cs | 56 +++++++ .../Overlays/AccountCreation/ScreenEntry.cs | 139 ++++++++++-------- 3 files changed, 136 insertions(+), 62 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/ProcessingOverlay.cs diff --git a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs index e503436d47..292a9bd088 100644 --- a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs +++ b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs @@ -8,6 +8,9 @@ using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { + /// + /// A loading spinner. + /// public class LoadingAnimation : VisibilityContainer { private readonly SpriteIcon spinner; diff --git a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs new file mode 100644 index 0000000000..0161c17ba9 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// An overlay that will consume all available space and block input when required. + /// Useful for disabling all elements in a form and showing we are waiting on a response, for instance. + /// + public class ProcessingOverlay : VisibilityContainer + { + private const float transition_duration = 200; + + public ProcessingOverlay() + { + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + Alpha = 0.9f, + }, + new LoadingAnimation { State = Visibility.Visible } + }; + } + + protected override bool Handle(UIEvent e) + { + return true; + } + + protected override void PopIn() + { + this.FadeIn(transition_duration * 2, Easing.OutQuint); + } + + protected override void PopOut() + { + this.FadeOut(transition_duration, Easing.OutQuint); + } + } +} diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 7328372db2..3d9a74ea2b 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -37,83 +38,88 @@ namespace osu.Game.Overlays.AccountCreation private IEnumerable characterCheckText; private OsuTextBox[] textboxes; + private ProcessingOverlay processingOverlay; [BackgroundDependencyLoader] private void load(OsuColour colours, APIAccess api) { this.api = api; - Child = new FillFlowContainer + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Padding = new MarginPadding(20), - Spacing = new Vector2(0, 10), - Children = new Drawable[] + new FillFlowContainer { - new OsuSpriteText + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 10), + Children = new Drawable[] { - TextSize = 20, - Margin = new MarginPadding { Vertical = 10 }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "Let's create an account!", - }, - usernameTextBox = new OsuTextBox - { - PlaceholderText = "username", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this - }, - usernameDescription = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - emailTextBox = new OsuTextBox - { - PlaceholderText = "email address", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this - }, - emailAddressDescription = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - passwordTextBox = new OsuPasswordTextBox - { - PlaceholderText = "password", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - }, - passwordDescription = new ErrorTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + new OsuSpriteText { - registerShake = new ShakeContainer + TextSize = 20, + Margin = new MarginPadding { Vertical = 10 }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Let's create an account!", + }, + usernameTextBox = new OsuTextBox + { + PlaceholderText = "username", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + usernameDescription = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + emailTextBox = new OsuTextBox + { + PlaceholderText = "email address", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this + }, + emailAddressDescription = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + passwordTextBox = new OsuPasswordTextBox + { + PlaceholderText = "password", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + passwordDescription = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = new SettingsButton + registerShake = new ShakeContainer { - Text = "Register", - Margin = new MarginPadding { Vertical = 20 }, - Action = performRegistration + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new SettingsButton + { + Text = "Register", + Margin = new MarginPadding { Vertical = 20 }, + Action = performRegistration + } } } - } + }, }, - } + }, + processingOverlay = new ProcessingOverlay { Alpha = 0 } }; textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox }; @@ -138,6 +144,12 @@ namespace osu.Game.Overlays.AccountCreation focusNextTextbox(); } + protected override void OnEntering(Screen last) + { + base.OnEntering(last); + processingOverlay.Hide(); + } + private void performRegistration() { if (focusNextTextbox()) @@ -150,6 +162,8 @@ namespace osu.Game.Overlays.AccountCreation emailAddressDescription.ClearErrors(); passwordDescription.ClearErrors(); + processingOverlay.Show(); + Task.Run(() => { bool success; @@ -181,6 +195,7 @@ namespace osu.Game.Overlays.AccountCreation } registerShake.Shake(); + processingOverlay.Hide(); return; } From b0e2b56e8593d530edba2efaf83ade51a5fcf9d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 16:54:08 +0900 Subject: [PATCH 068/355] Don't show warning screen if no previous account is detected --- .../Overlays/AccountCreation/ScreenWarning.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 9511f2f40c..b6fffde621 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -21,12 +22,26 @@ namespace osu.Game.Overlays.AccountCreation { private OsuTextFlowContainer multiAccountExplanationText; private LinkFlowContainer furtherAssistance; + private APIAccess api; private const string help_centre_url = "/help/wiki/Help_Centre#login"; + protected override void OnEntering(Screen last) + { + if (string.IsNullOrEmpty(api.ProvidedUsername)) + { + Content.FadeOut(); + Push(new ScreenEntry()); + return; + } + + base.OnEntering(last); + } + [BackgroundDependencyLoader(true)] private void load(OsuColour colours, APIAccess api, OsuGame game, TextureStore textures) { + this.api = api; Children = new Drawable[] { new Sprite From f157628dcc5bf074101250eea4344e15a07a0637 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 17:06:22 +0900 Subject: [PATCH 069/355] Remove unnecessary csproj change --- osu.Game/osu.Game.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 78496830d8..85eabb0350 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,4 @@ - - - From 1b6658f4eefac3454ff49a6c3f2007285ceacbe2 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 15:09:42 +0700 Subject: [PATCH 070/355] Move HealthIncreaseFor to Judgement --- .../Judgements/CatchBananaJudgement.cs | 2 +- .../Judgements/CatchDropletJudgement.cs | 2 +- .../Judgements/CatchJudgement.cs | 9 +-------- .../Judgements/CatchTinyDropletJudgement.cs | 2 +- .../Judgements/TaikoDrumRollJudgement.cs | 14 +++++++++++--- .../Judgements/TaikoDrumRollTickJudgement.cs | 2 +- .../Judgements/TaikoJudgement.cs | 19 +------------------ osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 4 ++-- osu.Game/Rulesets/Judgements/Judgement.cs | 14 ++++++++++++++ 10 files changed, 35 insertions(+), 37 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index f38009263f..d89d987f95 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Judgements } } - protected override float HealthIncreaseFor(HitResult result) + protected override double HealthIncreaseFor(HitResult result) { switch (result) { diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index 0df2305339..1fbf1db7f7 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Judgements } } - protected override float HealthIncreaseFor(HitResult result) + protected override double HealthIncreaseFor(HitResult result) { switch (result) { diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index 8a51867899..30ba868f6e 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.Judgements /// /// The to find the numeric health increase for. /// The numeric health increase of . - protected virtual float HealthIncreaseFor(HitResult result) + protected override double HealthIncreaseFor(HitResult result) { switch (result) { @@ -38,13 +38,6 @@ namespace osu.Game.Rulesets.Catch.Judgements } } - /// - /// Retrieves the numeric health increase of a . - /// - /// The to find the numeric health increase for. - /// The numeric health increase of . - public float HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); - /// /// Whether fruit on the platter should explode or drop. /// Note that this is only checked if the owning object is also diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index 8b77351027..fc933020d3 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Judgements } } - protected override float HealthIncreaseFor(HitResult result) + protected override double HealthIncreaseFor(HitResult result) { switch (result) { diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index e1a630e6b7..b3a64cd579 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -9,8 +9,16 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override bool AffectsCombo => false; - protected override int NumericResultFor(HitResult result) => 0; - - protected override double HealthIncreaseFor(HitResult result) => 0; + protected override double HealthIncreaseFor(HitResult result) + { + //Drum rolls can be ignored with no health penalty + switch (result) + { + case HitResult.Miss: + return 0; + default: + return base.HealthIncreaseFor(result); + } + } } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index c2675a7fac..86b495ca08 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements switch(result) { case HitResult.Great: - return 0.0000003; + return 0.15; default: return 0; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index bbdc14c6d4..4f397cda09 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -10,11 +10,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public override HitResult MaxResult => HitResult.Great; - /// - /// Computes the numeric result value for the combo portion of the score. - /// - /// The result to compute the value for. - /// The numeric result value. protected override int NumericResultFor(HitResult result) { switch (result) @@ -28,12 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements } } - /// - /// Retrieves the numeric health increase of a . - /// - /// The to find the numeric health increase for. - /// The numeric health increase of . - protected virtual double HealthIncreaseFor(HitResult result) + protected override double HealthIncreaseFor(HitResult result) { switch (result) { @@ -47,12 +37,5 @@ namespace osu.Game.Rulesets.Taiko.Judgements return 0; } } - - /// - /// Retrieves the numeric health increase of a . - /// - /// The to find the numeric health increase for. - /// The numeric health increase of . - public double HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 0dc460643a..89d0512e9c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -12,8 +12,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class DrumRoll : TaikoHitObject, IHasEndTime { - public override Judgement CreateJudgement() => new TaikoDrumRollJudgement(); - /// /// Drum roll distance that results in a duration of 1 speed-adjusted beat length. /// @@ -85,5 +83,7 @@ namespace osu.Game.Rulesets.Taiko.Objects first = false; } } + + public override Judgement CreateJudgement() => new TaikoDrumRollJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 67e2cae5eb..68433429c6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -10,8 +10,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class Swell : TaikoHitObject, IHasEndTime { - public override Judgement CreateJudgement() => new TaikoSwellJudgement(); - public double EndTime => StartTime + Duration; public double Duration { get; set; } @@ -30,5 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Objects for (int i = 0; i < RequiredHits; i++) AddNested(new SwellTick()); } + + public override Judgement CreateJudgement() => new TaikoSwellJudgement(); } } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index c679df5900..86a41a08ff 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -44,5 +44,19 @@ namespace osu.Game.Rulesets.Judgements /// The to find the numeric score representation for. /// The numeric score representation of . public int NumericResultFor(JudgementResult result) => NumericResultFor(result.Type); + + /// + /// Retrieves the numeric health increase of a . + /// + /// The to find the numeric health increase for. + /// The numeric health increase of . + protected virtual double HealthIncreaseFor(HitResult result) => 0; + + /// + /// Retrieves the numeric health increase of a . + /// + /// The to find the numeric health increase for. + /// The numeric health increase of . + public double HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); } } From 6ebe555838fd458ec907a6254d84787935a8eb6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 17:11:39 +0900 Subject: [PATCH 071/355] Fix incorrect filename --- .../Online/API/{RegsitrationRequest.cs => RegistrationRequest.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game/Online/API/{RegsitrationRequest.cs => RegistrationRequest.cs} (100%) diff --git a/osu.Game/Online/API/RegsitrationRequest.cs b/osu.Game/Online/API/RegistrationRequest.cs similarity index 100% rename from osu.Game/Online/API/RegsitrationRequest.cs rename to osu.Game/Online/API/RegistrationRequest.cs From 8cae549541ee4f3d53c6cd1bdd7279c247844230 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 15:58:03 +0700 Subject: [PATCH 072/355] Remove unused TaikoScoreProcessor constants --- .../Scoring/TaikoScoreProcessor.cs | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 84f87bf10c..721d435780 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -17,38 +17,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// private const double hp_hit_great = 0.03; - /// - /// The HP awarded for a hit. - /// - private const double hp_hit_good = 0.011; - - /// - /// The minimum HP deducted for a . - /// This occurs when HP Drain = 0. - /// - private const double hp_miss_min = -0.0018; - - /// - /// The median HP deducted for a . - /// This occurs when HP Drain = 5. - /// - private const double hp_miss_mid = -0.0075; - - /// - /// The maximum HP deducted for a . - /// This occurs when HP Drain = 10. - /// - private const double hp_miss_max = -0.012; - - /// - /// The HP awarded for a hit. - /// - /// hits award less HP as they're more spammable, although in hindsight - /// this probably awards too little HP and is kept at this value for now for compatibility. - /// - /// - private const double hp_hit_tick = 0.00000003; - /// /// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// From 42817b98f9ed6bb1081d65662992116a03fffb75 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Dec 2018 18:16:17 +0900 Subject: [PATCH 073/355] Hide max participants box --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 3 ++- osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index af41563e30..463002fbcb 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing.Input; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; @@ -38,9 +39,9 @@ namespace osu.Game.Tests.Visual { RelativeSizeAxes = Axes.Both, Height = 0.75f, + State = Visibility.Visible }); - AddStep(@"show", overlay.Show); assertAll(); AddStep(@"set name", () => overlay.CurrentName = @"Two Testing Room"); AddStep(@"set max", () => overlay.CurrentMaxParticipants = null); diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index 99afc437d0..467b936538 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -33,6 +33,7 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Container content; + private readonly OsuSpriteText typeLabel; protected readonly OsuTextBox NameField, MaxParticipantsField; @@ -115,6 +116,8 @@ namespace osu.Game.Screens.Multi.Components { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, + Alpha = 0.2f, + ReadOnly = true, OnCommit = (sender, text) => apply(), }, }, From c02150a19b816955a5222159508a30b07b19d829 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Dec 2018 18:31:12 +0900 Subject: [PATCH 074/355] Make match header not fade when beatmap changes --- osu.Game.Tests/Visual/TestCaseMatch.cs | 3 ++- osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs | 1 - osu.Game/Screens/Multi/Screens/Match/Header.cs | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index ae19b9720e..6099ed41bb 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -20,7 +20,8 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(TestCaseMatch), - typeof(GameTypePicker) + typeof(GameTypePicker), + typeof(RoomSettingsOverlay) }; [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index 467b936538..bd9b269452 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -168,7 +168,6 @@ namespace osu.Game.Screens.Multi.Components new GameTypeTeamVersus(), }; - Room = new Room(); } diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index e4a7baf035..50db63e3e3 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Multi.Screens.Match { RelativeSizeAxes = Axes.Both, Masking = true, - Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } + Child = background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } }, new Box { @@ -175,6 +175,11 @@ namespace osu.Game.Screens.Multi.Screens.Match return base.OnMouseUp(e); } } + + private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double FadeDuration => 0; + } } public enum MatchHeaderPage From 10b526504aa230642b5b7c708431126d8e142118 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 6 Dec 2018 19:29:18 +0900 Subject: [PATCH 075/355] Move ModOverlay to SongSelect --- osu.Game/Screens/Select/PlaySongSelect.cs | 21 +-------------------- osu.Game/Screens/Select/SongSelect.cs | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 0e3dfcf284..8d37da0377 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -9,12 +9,10 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Overlays; -using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; @@ -25,19 +23,11 @@ namespace osu.Game.Screens.Select public class PlaySongSelect : SongSelect { private OsuScreen player; - private readonly ModSelectOverlay modSelect; protected readonly BeatmapDetailArea BeatmapDetails; private bool removeAutoModOnResume; public PlaySongSelect() { - FooterPanels.Add(modSelect = new ModSelectOverlay - { - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - }); - LeftContent.Add(BeatmapDetails = new BeatmapDetailArea { RelativeSizeAxes = Axes.Both, @@ -60,8 +50,6 @@ namespace osu.Game.Screens.Select sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); - Footer.AddButton(@"mods", colours.Yellow, modSelect, Key.F1, float.MaxValue); - BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1); BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, null, Key.Number2); BeatmapOptions.AddButton(@"Edit", @"beatmap", FontAwesome.fa_pencil, colours.Yellow, () => @@ -115,7 +103,7 @@ namespace osu.Game.Screens.Select if (removeAutoModOnResume) { var autoType = Ruleset.Value.CreateInstance().GetAutoplayMod().GetType(); - modSelect.DeselectTypes(new[] { autoType }, true); + ModSelect.DeselectTypes(new[] { autoType }, true); removeAutoModOnResume = false; } @@ -126,13 +114,6 @@ namespace osu.Game.Screens.Select base.OnResuming(last); } - protected override void OnSuspending(Screen next) - { - modSelect.Hide(); - - base.OnSuspending(next); - } - protected override bool OnExiting(Screen next) { if (base.OnExiting(next)) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 66540c6900..c7e999f7c7 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -21,6 +21,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; using osu.Game.Overlays; +using osu.Game.Overlays.Mods; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Backgrounds; @@ -67,6 +68,8 @@ namespace osu.Game.Screens.Select private DialogOverlay dialogOverlay; private BeatmapManager beatmaps; + protected readonly ModSelectOverlay ModSelect; + private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeBeatmap; @@ -194,7 +197,16 @@ namespace osu.Game.Screens.Select OnBack = ExitFromBack, }); - FooterPanels.Add(BeatmapOptions = new BeatmapOptionsOverlay()); + FooterPanels.AddRange(new Drawable[] + { + BeatmapOptions = new BeatmapOptionsOverlay(), + ModSelect = new ModSelectOverlay + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + } + }); } } @@ -205,6 +217,7 @@ namespace osu.Game.Screens.Select { if (Footer != null) { + Footer.AddButton(@"mods", colours.Yellow, ModSelect, Key.F1); Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(@"options", colours.Blue, BeatmapOptions, Key.F3); @@ -438,6 +451,8 @@ namespace osu.Game.Screens.Select protected override void OnSuspending(Screen next) { + ModSelect.Hide(); + Content.ScaleTo(1.1f, 250, Easing.InSine); Content.FadeOut(250); @@ -448,6 +463,12 @@ namespace osu.Game.Screens.Select protected override bool OnExiting(Screen next) { + if (ModSelect.State == Visibility.Visible) + { + ModSelect.Hide(); + return true; + } + FinaliseSelection(performStartAction: false); beatmapInfoWedge.State = Visibility.Hidden; From 46b98702e1ce0149e6c0e70e1b8325559f644488 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Thu, 6 Dec 2018 12:48:11 +0100 Subject: [PATCH 076/355] make target animation call more obvious --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 2 +- .../Objects/Drawables/DrawableOsuBlinds.cs | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 9f33653bc7..cfdc63a57e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.Health.ValueChanged += val => { - flashlight.Value = (float)val; + flashlight.AnimateTarget((float)val); }; scoreProcessor.Combo.ValueChanged += val => { if (val > 0 && val % 30 == 0) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index 7e72c5c7bb..eb725e09db 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -305,17 +305,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// /// Health between 0 and 1 for the blinds to base the width on. Will get animated for 200ms using out-quintic easing. /// - public float Value + public void AnimateTarget(float value) { - set - { - target = value; - this.TransformTo(nameof(easing), target, 200, Easing.OutQuint); - } - get - { - return target; - } + target = value; + this.TransformTo(nameof(easing), target, 200, Easing.OutQuint); + } + + public float Target + { + get => target; } public Texture PanelTexture From a14de5bd1b9a3b38102cf5e8a060184ddbedc1af Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Thu, 6 Dec 2018 12:52:39 +0100 Subject: [PATCH 077/355] Remove blinds random NPC --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 - .../Objects/Drawables/DrawableOsuBlinds.cs | 92 ------------------- 2 files changed, 96 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index cfdc63a57e..a9379c9133 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -33,10 +33,6 @@ namespace osu.Game.Rulesets.Osu.Mods scoreProcessor.Health.ValueChanged += val => { flashlight.AnimateTarget((float)val); }; - scoreProcessor.Combo.ValueChanged += val => { - if (val > 0 && val % 30 == 0) - flashlight.TriggerNpc(); - }; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index eb725e09db..df7006da1d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -12,7 +12,6 @@ using osu.Game.Skinning; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK; using osuTK.Graphics; -using System; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -28,14 +27,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Sprite panelLeft, panelRight; private Sprite bgPanelLeft, bgPanelRight; - private Drawable bgRandomNpc; - private Drawable randomNpc; private const float npc_movement_start = 1.5f; private float npcPosition = npc_movement_start; private bool animatingBlinds; private readonly Beatmap beatmap; - private Random random; private ISkinSource skin; @@ -122,36 +118,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Depth = fg_panel_depth }); - // seed with unique seed per map so NPC always comes from the same sides for a same map for reproducible replays. - random = new Random(beatmap.Metadata.ToString().GetHashCode()); - Add(bgRandomNpc = new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = Color4.Black, - Width = 512 * 0.4f, - Height = 512 * 0.95f, - RelativePositionAxes = Axes.Y, - X = -512, - Y = 0, - Depth = black_depth, - Alpha = 0 - }); - Add(new SkinnableDrawable("Play/Catch/fruit-catcher-idle", name => randomNpc = new Sprite - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Texture = textures.Get(name), - Width = 512, - Height = 512, - RelativePositionAxes = Axes.Y, - X = -512, - Y = 0, - Alpha = 0 - }) { - Depth = npc_depth - }); - this.skin = skin; skin.SourceChanged += skinChanged; PanelTexture = textures.Get("Play/osu/blinds-panel"); @@ -205,11 +171,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables panelRight.X = end - width; bgPanelLeft.X = start; bgPanelRight.X = end; - - float adjustedNpcPosition = npcPosition * rawWidth; - if (randomNpc != null) - randomNpc.X = adjustedNpcPosition; - bgRandomNpc.X = adjustedNpcPosition; } protected override void LoadComplete() @@ -249,59 +210,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables this.TransformTo(nameof(targetBreakMultiplier), 1f, 2500, Easing.OutBounce); } - public void TriggerNpc() - { - if (animatingBlinds) - return; - - bool left = (random.Next() & 1) != 0; - bool exit = (random.Next() & 1) != 0; - float start, end; - - if (left) - { - start = -npc_movement_start; - end = npc_movement_start; - - randomNpc.Scale = new Vector2(1, 1); - } - else - { - start = npc_movement_start; - end = -npc_movement_start; - - randomNpc.Scale = new Vector2(-1, 1); - } - - // depths for exit from the left and entry from the right - if (left == exit) - { - ChangeChildDepth(bgPanelLeft, fg_panel_depth + 1); - ChangeChildDepth(panelLeft, fg_panel_depth); - - ChangeChildDepth(bgPanelRight, bg_panel_depth + 1); - ChangeChildDepth(panelRight, bg_panel_depth); - } - else // depths for entry from the left or exit from the right - { - ChangeChildDepth(bgPanelLeft, bg_panel_depth + 1); - ChangeChildDepth(panelLeft, bg_panel_depth); - - ChangeChildDepth(bgPanelRight, fg_panel_depth + 1); - ChangeChildDepth(panelRight, fg_panel_depth); - } - - animatingBlinds = true; - npcPosition = start; - this.TransformTo(nameof(npcPosition), end, 3000, Easing.OutSine).Finally(_ => animatingBlinds = false); - - targetClamp = 1; - this.Delay(600).TransformTo(nameof(targetClamp), 0.6f, 300).Delay(500).TransformTo(nameof(targetClamp), 1f, 300); - - randomNpc?.FadeIn(250).Delay(2000).FadeOut(500); - bgRandomNpc.FadeIn(250).Delay(2000).FadeOut(500); - } - /// /// Health between 0 and 1 for the blinds to base the width on. Will get animated for 200ms using out-quintic easing. /// From cb2444e01cd34e16d4e196581bc99698a4208c17 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 19:04:54 +0700 Subject: [PATCH 078/355] Remove Meh from TaikoHitWindows --- .../Objects/ManiaHitWindows.cs | 5 +-- .../Objects/Drawables/DrawableHit.cs | 6 +-- .../Objects/TaikoHitWindows.cs | 19 +++++++-- osu.Game/Rulesets/Objects/HitWindows.cs | 42 ++++++++++--------- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs index 063b626af1..ad0c04b4cc 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs @@ -20,11 +20,10 @@ namespace osu.Game.Rulesets.Mania.Objects { HitResult.Miss, (376, 346, 316) }, }; + public override bool IsHitResultAllowed(HitResult result) => true; + public override void SetDifficulty(double difficulty) { - AllowsPerfect = true; - AllowsOk = true; - Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 8c19e64de6..d4f0360b40 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } var result = HitObject.HitWindows.ResultFor(timeOffset); - if (result <= HitResult.Miss) + if (result == HitResult.None) return; if (!validActionPressed) @@ -173,12 +173,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { - if (timeOffset > second_hit_window) + if (timeOffset - MainObject.Result.TimeOffset > second_hit_window) ApplyResult(r => r.Type = HitResult.Miss); return; } - if (Math.Abs(MainObject.Result.TimeOffset - timeOffset) < second_hit_window) + if (Math.Abs(timeOffset - MainObject.Result.TimeOffset) <= second_hit_window) ApplyResult(r => r.Type = MainObject.Result.Type); } diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index 289f084a45..722a327f45 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -14,15 +14,28 @@ namespace osu.Game.Rulesets.Taiko.Objects { { HitResult.Great, (100, 70, 40) }, { HitResult.Good, (240, 160, 100) }, - { HitResult.Meh, (270, 190, 140) }, - { HitResult.Miss, (400, 400, 400) }, + { HitResult.Miss, (270, 190, 140) }, }; + protected override double SuccessfulHitWindow => Good; + + public override bool IsHitResultAllowed(HitResult result) + { + switch (result) + { + case HitResult.Great: + case HitResult.Good: + case HitResult.Miss: + return true; + default: + return false; + } + } + public override void SetDifficulty(double difficulty) { Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); - Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); } } diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 3717209860..621fb418eb 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -22,7 +22,6 @@ namespace osu.Game.Rulesets.Objects /// /// Hit window for a result. - /// The user can only achieve receive this result if is true. /// public double Perfect { get; protected set; } @@ -38,7 +37,6 @@ namespace osu.Game.Rulesets.Objects /// /// Hit window for an result. - /// The user can only achieve this result if is true. /// public double Ok { get; protected set; } @@ -53,14 +51,25 @@ namespace osu.Game.Rulesets.Objects public double Miss { get; protected set; } /// - /// Whether it's possible to achieve a result. + /// Hit window for a non- result. /// - public bool AllowsPerfect; + protected virtual double SuccessfulHitWindow => Meh; /// - /// Whether it's possible to achieve a result. + /// Whether it's possible to achieve this . /// - public bool AllowsOk; + /// The result. + public virtual bool IsHitResultAllowed(HitResult result) + { + switch(result) + { + case HitResult.Perfect: + case HitResult.Ok: + return false; + default: + return true; + } + } /// /// Sets hit windows with values that correspond to a difficulty parameter. @@ -85,18 +94,11 @@ namespace osu.Game.Rulesets.Objects { timeOffset = Math.Abs(timeOffset); - if (AllowsPerfect && timeOffset <= HalfWindowFor(HitResult.Perfect)) - return HitResult.Perfect; - if (timeOffset <= HalfWindowFor(HitResult.Great)) - return HitResult.Great; - if (timeOffset <= HalfWindowFor(HitResult.Good)) - return HitResult.Good; - if (AllowsOk && timeOffset <= HalfWindowFor(HitResult.Ok)) - return HitResult.Ok; - if (timeOffset <= HalfWindowFor(HitResult.Meh)) - return HitResult.Meh; - if (timeOffset <= HalfWindowFor(HitResult.Miss)) - return HitResult.Miss; + for(var result = HitResult.Perfect; result >= HitResult.Miss; --result) + { + if(IsHitResultAllowed(result) && timeOffset <= HalfWindowFor(result)) + return result; + } return HitResult.None; } @@ -130,10 +132,10 @@ namespace osu.Game.Rulesets.Objects /// /// Given a time offset, whether the can ever be hit in the future with a non- result. - /// This happens if is less than what is required for a result. + /// This happens if is less than what is required for a result. /// /// The time offset. /// Whether the can be hit at any point in the future from this time offset. - public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(HitResult.Meh); + public bool CanBeHit(double timeOffset) => timeOffset <= SuccessfulHitWindow / 2; } } From aa79758db5250ff63b7b398260649aabefa62fb1 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 19:15:41 +0700 Subject: [PATCH 079/355] Remove unnecessary float literal --- osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index 30ba868f6e..a266dfa691 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Judgements default: return 0; case HitResult.Perfect: - return 10.2f; + return 10.2; } } From 407f9d2e78dcf29a784e623059c9a417595bd9c7 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 19:33:42 +0700 Subject: [PATCH 080/355] Comment cleanup --- osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs | 5 ----- osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index a266dfa691..b20bc43886 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -22,11 +22,6 @@ namespace osu.Game.Rulesets.Catch.Judgements } } - /// - /// Retrieves the numeric health increase of a . - /// - /// The to find the numeric health increase for. - /// The numeric health increase of . protected override double HealthIncreaseFor(HitResult result) { switch (result) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index b3a64cd579..8c88d6d073 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements protected override double HealthIncreaseFor(HitResult result) { - //Drum rolls can be ignored with no health penalty + // Drum rolls can be ignored with no health penalty switch (result) { case HitResult.Miss: From 394c038c33b7120adca8d621c6ada2ec66309b1a Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 19:52:16 +0700 Subject: [PATCH 081/355] Removed unnecessary JudgementResult casts --- .../Scoring/CatchScoreProcessor.cs | 3 +-- .../Scoring/TaikoScoreProcessor.cs | 15 ++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 403cedde8c..d33b2ae8d3 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -40,8 +40,7 @@ namespace osu.Game.Rulesets.Catch.Scoring return; } - if (result.Judgement is CatchJudgement catchJudgement) - Health.Value += Math.Max(catchJudgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; + Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 721d435780..9233ab8eb7 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -43,17 +43,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyResult(result); - if (result.Judgement is TaikoJudgement taikoJudgement) - { - double hpIncrease = taikoJudgement.HealthIncreaseFor(result); + double hpIncrease = result.Judgement.HealthIncreaseFor(result); - if (result.Type == HitResult.Miss) - hpIncrease *= hpMissMultiplier; - else - hpIncrease *= hpMultiplier; + if (result.Type == HitResult.Miss) + hpIncrease *= hpMissMultiplier; + else + hpIncrease *= hpMultiplier; - Health.Value += hpIncrease; - } + Health.Value += hpIncrease; } protected override void Reset(bool storeResults) From 94f01b6678096c85630225acbcb60096c878fe05 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Thu, 6 Dec 2018 20:05:03 +0700 Subject: [PATCH 082/355] Remove unused using directives --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 1 - osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index d33b2ae8d3..778d972b52 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -3,7 +3,6 @@ using System; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 9233ab8eb7..058d2b4beb 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -4,7 +4,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.UI; From 6eff7d9acc18cd8768de3d0baa85fd185dc28df1 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Thu, 6 Dec 2018 14:34:10 +0100 Subject: [PATCH 083/355] Style fixes --- .../Objects/Drawables/DrawableOsuBlinds.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs index df7006da1d..d06f1250d8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs @@ -27,10 +27,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Sprite panelLeft, panelRight; private Sprite bgPanelLeft, bgPanelRight; - private const float npc_movement_start = 1.5f; - private float npcPosition = npc_movement_start; - private bool animatingBlinds; - private readonly Beatmap beatmap; private ISkinSource skin; @@ -43,7 +39,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private const float black_depth = 10; private const float bg_panel_depth = 8; private const float fg_panel_depth = 4; - private const float npc_depth = 6; private readonly CompositeDrawable restrictTo; private readonly bool modEasy, modHardrock; @@ -210,6 +205,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables this.TransformTo(nameof(targetBreakMultiplier), 1f, 2500, Easing.OutBounce); } + /// + /// Value between 0 and 1 setting a maximum "closedness" for the blinds. + /// Useful for animating how far the blinds can be opened while keeping them at the original position if they are wider open than this. + /// + public float TargetClamp + { + get => targetClamp; + set => targetClamp = value; + } + /// /// Health between 0 and 1 for the blinds to base the width on. Will get animated for 200ms using out-quintic easing. /// From 2122966cd41a4435496f3e525a2e2aa9b5682394 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Dec 2018 20:56:33 +0900 Subject: [PATCH 084/355] Show channel selector when no channels are joined --- .../Overlays/Chat/Tabs/ChannelTabControl.cs | 5 ++-- osu.Game/Overlays/ChatOverlay.cs | 28 ++++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 79cb0a4d14..dc72c8053a 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -94,13 +94,12 @@ namespace osu.Game.Overlays.Chat.Tabs { if (tab is ChannelSelectorTabItem) { - tab.Active.Toggle(); + tab.Active.Value = true; return; } - selectorTab.Active.Value = false; - base.SelectTab(tab); + selectorTab.Active.Value = false; } private void tabCloseRequested(TabItem tab) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index bdb28d1246..75e22f85d1 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -52,9 +52,9 @@ namespace osu.Game.Overlays public Bindable ChatHeight { get; set; } private readonly Container channelSelectionContainer; - private readonly ChannelSelectionOverlay channelSelection; + private readonly ChannelSelectionOverlay channelSelectionOverlay; - public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.ReceivePositionalInputAt(screenSpacePos); + public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelectionOverlay.State == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos); public ChatOverlay() { @@ -74,7 +74,7 @@ namespace osu.Game.Overlays Masking = true, Children = new[] { - channelSelection = new ChannelSelectionOverlay + channelSelectionOverlay = new ChannelSelectionOverlay { RelativeSizeAxes = Axes.Both, }, @@ -161,9 +161,16 @@ namespace osu.Game.Overlays }; channelTabControl.Current.ValueChanged += chat => channelManager.CurrentChannel.Value = chat; - channelTabControl.ChannelSelectorActive.ValueChanged += value => channelSelection.State = value ? Visibility.Visible : Visibility.Hidden; - channelSelection.StateChanged += state => + channelTabControl.ChannelSelectorActive.ValueChanged += value => channelSelectionOverlay.State = value ? Visibility.Visible : Visibility.Hidden; + channelSelectionOverlay.StateChanged += state => { + if (state == Visibility.Hidden && channelManager.CurrentChannel.Value == null) + { + channelSelectionOverlay.State = Visibility.Visible; + State = Visibility.Hidden; + return; + } + channelTabControl.ChannelSelectorActive.Value = state == Visibility.Visible; if (state == Visibility.Visible) @@ -176,8 +183,8 @@ namespace osu.Game.Overlays textbox.HoldFocus = true; }; - channelSelection.OnRequestJoin = channel => channelManager.JoinChannel(channel); - channelSelection.OnRequestLeave = channel => channelManager.LeaveChannel(channel); + channelSelectionOverlay.OnRequestJoin = channel => channelManager.JoinChannel(channel); + channelSelectionOverlay.OnRequestLeave = channel => channelManager.LeaveChannel(channel); } private void currentChannelChanged(Channel channel) @@ -186,6 +193,7 @@ namespace osu.Game.Overlays { textbox.Current.Disabled = true; currentChannelContainer.Clear(false); + channelSelectionOverlay.State = Visibility.Visible; return; } @@ -239,7 +247,7 @@ namespace osu.Game.Overlays double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y; // If the channel selection screen is shown, mind its minimum height - if (channelSelection.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) + if (channelSelectionOverlay.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) targetChatHeight = 1f - channel_selection_min_height; ChatHeight.Value = targetChatHeight; @@ -305,7 +313,7 @@ namespace osu.Game.Overlays channelManager.AvailableChannels.ItemsRemoved += availableChannelsChanged; //for the case that channelmanager was faster at fetching the channels than our attachment to CollectionChanged. - channelSelection.UpdateAvailableChannels(channelManager.AvailableChannels); + channelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels); foreach (Channel channel in channelManager.JoinedChannels) channelTabControl.AddChannel(channel); } @@ -326,7 +334,7 @@ namespace osu.Game.Overlays } private void availableChannelsChanged(IEnumerable channels) - => channelSelection.UpdateAvailableChannels(channelManager.AvailableChannels); + => channelSelectionOverlay.UpdateAvailableChannels(channelManager.AvailableChannels); protected override void Dispose(bool isDisposing) { From 2f9de149dd28dd7980ce22afe565fa860629e926 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 13:56:21 +0900 Subject: [PATCH 085/355] Add constructor to create a PM channel from a User --- osu.Game/Online/Chat/Channel.cs | 11 +++++++++++ osu.Game/Online/Chat/ChannelManager.cs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 9d3b7b5cc9..9dc357c403 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -88,6 +88,17 @@ namespace osu.Game.Online.Chat { } + /// + /// Create a private messaging channel with the specified user. + /// + /// The user to create the private conversation with. + public Channel(User user) + { + Type = ChannelType.PM; + Users.Add(user); + Name = user.Username; + } + /// /// Adds the argument message as a local echo. When this local echo is resolved will get called. /// diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 29f971078b..863ad3042f 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -79,7 +79,7 @@ namespace osu.Game.Online.Chat throw new ArgumentNullException(nameof(user)); CurrentChannel.Value = JoinedChannels.FirstOrDefault(c => c.Type == ChannelType.PM && c.Users.Count == 1 && c.Users.Any(u => u.Id == user.Id)) - ?? new Channel { Name = user.Username, Users = { user }, Type = ChannelType.PM }; + ?? new Channel(user); } private void currentChannelChanged(Channel channel) => JoinChannel(channel); From d42c45c87ea3befb2ec5c9c1d4301b2f13cd077d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 14:00:16 +0900 Subject: [PATCH 086/355] Add full tests --- .../Visual/TestCaseChannelTabControl.cs | 65 +++++++++---------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs index 447337bef0..1127402adb 100644 --- a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs @@ -4,15 +4,12 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; @@ -74,50 +71,50 @@ namespace osu.Game.Tests.Visual channelTabControl.OnRequestLeave += channel => channelTabControl.RemoveChannel(channel); channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.ToString(); - AddStep("Add random private channel", addRandomUser); + AddStep("Add random private channel", addRandomPrivateChannel); AddAssert("There is only one channels", () => channelTabControl.Items.Count() == 2); - AddRepeatStep("Add 3 random private channels", addRandomUser, 3); + AddRepeatStep("Add 3 random private channels", addRandomPrivateChannel, 3); AddAssert("There are four channels", () => channelTabControl.Items.Count() == 5); AddStep("Add random public channel", () => addChannel(RNG.Next().ToString())); - AddRepeatStep("Select a random channel", () => channelTabControl.Current.Value = channelTabControl.Items.ElementAt(RNG.Next(channelTabControl.Items.Count())), 20); - } + AddRepeatStep("Select a random channel", () => channelTabControl.Current.Value = channelTabControl.Items.ElementAt(RNG.Next(channelTabControl.Items.Count() - 1)), 20); - private List users; + Channel channelBefore = channelTabControl.Items.First(); + AddStep("set first channel", () => channelTabControl.Current.Value = channelBefore); - private void addRandomUser() - { - channelTabControl.AddChannel(new Channel + AddStep("select selector tab", () => channelTabControl.Current.Value = channelTabControl.Items.Last()); + AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value); + + AddAssert("check channel unchanged", () => channelBefore == channelTabControl.Current.Value); + + AddStep("set second channel", () => channelTabControl.Current.Value = channelTabControl.Items.Skip(1).First()); + AddAssert("selector tab is inactive", () => !channelTabControl.ChannelSelectorActive.Value); + + AddUntilStep(() => { - Users = - { - users?.Count > 0 - ? users[RNG.Next(0, users.Count - 1)] - : new User - { - Id = RNG.Next(), - Username = "testuser" + RNG.Next(1000) - } - } - }); + var first = channelTabControl.Items.First(); + if (first.Name == "+") + return true; + + channelTabControl.RemoveChannel(first); + return false; + }, "remove all channels"); + + AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value); } - private void addChannel(string name) - { + private void addRandomPrivateChannel() => + channelTabControl.AddChannel(new Channel(new User + { + Id = RNG.Next(1000, 10000000), + Username = "Test User " + RNG.Next(1000) + })); + + private void addChannel(string name) => channelTabControl.AddChannel(new Channel { Type = ChannelType.Public, Name = name }); - } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api) - { - GetUsersRequest req = new GetUsersRequest(); - req.Success += list => users = list.Select(e => e.User).ToList(); - - api.Queue(req); - } } } From d68b4bb8e7809a704755373dff76fb61a49a863c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Dec 2018 14:28:43 +0900 Subject: [PATCH 087/355] Remove custom action from DrawableRoom --- osu.Game/Screens/Multi/Components/DrawableRoom.cs | 9 --------- osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 30bee7829e..6bdc4c2f2d 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -10,7 +10,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; @@ -36,8 +35,6 @@ namespace osu.Game.Screens.Multi.Components public event Action StateChanged; - public Action SelectionRequested; - private readonly Box selectionBox; private readonly Bindable nameBind = new Bindable(); @@ -244,11 +241,5 @@ namespace osu.Game.Screens.Multi.Components base.LoadComplete(); this.FadeInFromZero(transition_duration); } - - protected override bool OnClick(ClickEvent e) - { - SelectionRequested?.Invoke(); - return true; - } } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index f307032600..f4dd45bdfb 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { var drawableRoom = new DrawableRoom(room); - drawableRoom.SelectionRequested = () => selectionRequested(drawableRoom); + drawableRoom.Action = () => selectionRequested(drawableRoom); RoomsContainer.Add(drawableRoom); From 29263d71544c9613c8c14f71c4f36ed0d775a8f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Dec 2018 16:20:05 +0900 Subject: [PATCH 088/355] Refactor bindable shenanigans in Match --- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 22 +++--- .../Visual/TestCaseMatchParticipants.cs | 10 +-- .../Screens/Multi/Screens/Lounge/Lounge.cs | 2 +- osu.Game/Screens/Multi/Screens/Match/Info.cs | 67 ++++++------------- osu.Game/Screens/Multi/Screens/Match/Match.cs | 44 ++++++------ .../Multi/Screens/Match/Participants.cs | 48 +++++++------ .../Multi/Screens/MultiplayerScreen.cs | 3 +- 7 files changed, 85 insertions(+), 111 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 205da6932f..6998ff4c39 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -19,10 +19,10 @@ namespace osu.Game.Tests.Visual Info info = new Info(); Add(info); - AddStep(@"set name", () => info.Name = @"Room Name?"); - AddStep(@"set availability", () => info.Availability = RoomAvailability.FriendsOnly); - AddStep(@"set status", () => info.Status = new RoomStatusPlaying()); - AddStep(@"set beatmap", () => info.Beatmap = new BeatmapInfo + AddStep(@"set name", () => info.Name.Value = @"Room Name?"); + AddStep(@"set availability", () => info.Availability.Value = RoomAvailability.FriendsOnly); + AddStep(@"set status", () => info.Status.Value = new RoomStatusPlaying()); + AddStep(@"set beatmap", () => info.Beatmap.Value = new BeatmapInfo { StarDifficulty = 2.4, Ruleset = rulesets.GetRuleset(0), @@ -34,14 +34,14 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set type", () => info.Type = new GameTypeTagTeam()); + AddStep(@"set type", () => info.Type.Value = new GameTypeTagTeam()); - AddStep(@"change name", () => info.Name = @"Room Name!"); - AddStep(@"change availability", () => info.Availability = RoomAvailability.InviteOnly); - AddStep(@"change status", () => info.Status = new RoomStatusOpen()); - AddStep(@"null beatmap", () => info.Beatmap = null); - AddStep(@"change type", () => info.Type = new GameTypeTeamVersus()); - AddStep(@"change beatmap", () => info.Beatmap = new BeatmapInfo + AddStep(@"change name", () => info.Name.Value = @"Room Name!"); + AddStep(@"change availability", () => info.Availability.Value = RoomAvailability.InviteOnly); + AddStep(@"change status", () => info.Status.Value = new RoomStatusOpen()); + AddStep(@"null beatmap", () => info.Beatmap.Value = null); + AddStep(@"change type", () => info.Type.Value = new GameTypeTeamVersus()); + AddStep(@"change beatmap", () => info.Beatmap.Value = new BeatmapInfo { StarDifficulty = 4.2, Ruleset = rulesets.GetRuleset(3), diff --git a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs index d6ae07252b..6024ec8ea6 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs @@ -19,8 +19,8 @@ namespace osu.Game.Tests.Visual RelativeSizeAxes = Axes.Both, }); - AddStep(@"set max to null", () => participants.Max = null); - AddStep(@"set users", () => participants.Users = new[] + AddStep(@"set max to null", () => participants.MaxParticipants.Value = null); + AddStep(@"set users", () => participants.Users.Value = new[] { new User { @@ -48,9 +48,9 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set max", () => participants.Max = 10); - AddStep(@"clear users", () => participants.Users = new User[] { }); - AddStep(@"set max to null", () => participants.Max = null); + AddStep(@"set max", () => participants.MaxParticipants.Value = 10); + AddStep(@"clear users", () => participants.Users.Value = new User[] { }); + AddStep(@"set max to null", () => participants.MaxParticipants.Value = null); } } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index f4dd45bdfb..140b3550c1 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge public override string Title => "Lounge"; - protected override Container TransitionContent => content; + protected override Drawable TransitionContent => content; public Lounge() { diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Screens/Match/Info.cs index a2c056c8bd..fc6e84c38a 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Info.cs @@ -23,60 +23,26 @@ namespace osu.Game.Screens.Multi.Screens.Match { public const float HEIGHT = 128; - private readonly OsuSpriteText name, availabilityStatus; - private readonly BeatmapTypeInfo beatmapTypeInfo; + private readonly OsuSpriteText availabilityStatus; private readonly ReadyButton readyButton; private OsuColour colours; public Bindable Ready => readyButton.Ready; - public string Name - { - set { name.Text = value; } - } - - private RoomAvailability availability; - public RoomAvailability Availability - { - set - { - if (value == availability) return; - availability = value; - - if (IsLoaded) - updateAvailabilityStatus(); - } - } - - private RoomStatus status; - public RoomStatus Status - { - set - { - if (value == status) return; - status = value; - - if (IsLoaded) - updateAvailabilityStatus(); - } - } - - public BeatmapInfo Beatmap - { - set { beatmapTypeInfo.Beatmap = value; } - } - - public GameType Type - { - set { beatmapTypeInfo.Type = value; } - } + public readonly Bindable Name = new Bindable(); + public readonly Bindable Availability = new Bindable(); + public readonly Bindable Status = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Type = new Bindable(); public Info() { RelativeSizeAxes = Axes.X; Height = HEIGHT; + BeatmapTypeInfo beatmapTypeInfo; + Children = new Drawable[] { new Box @@ -103,9 +69,10 @@ namespace osu.Game.Screens.Multi.Screens.Match Direction = FillDirection.Vertical, Children = new Drawable[] { - name = new OsuSpriteText + new OsuSpriteText { TextSize = 30, + Current = Name }, availabilityStatus = new OsuSpriteText { @@ -131,6 +98,11 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }, }; + + Availability.BindValueChanged(_ => updateAvailabilityStatus()); + Status.BindValueChanged(_ => updateAvailabilityStatus()); + Beatmap.BindValueChanged(b => beatmapTypeInfo.Beatmap = b); + Type.BindValueChanged(t => beatmapTypeInfo.Type = t); } [BackgroundDependencyLoader] @@ -148,10 +120,13 @@ namespace osu.Game.Screens.Multi.Screens.Match private void updateAvailabilityStatus() { - if (status != null) + if (!IsLoaded) + return; + + if (Status.Value != null) { - availabilityStatus.FadeColour(status.GetAppropriateColour(colours), 100); - availabilityStatus.Text = $"{availability.GetDescription()}, {status.Message}"; + availabilityStatus.FadeColour(Status.Value.GetAppropriateColour(colours), 100); + availabilityStatus.Text = $"{Availability.Value.GetDescription()}, {Status.Value.Message}"; } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 468390b75b..4f81ffd305 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -20,15 +20,14 @@ namespace osu.Game.Screens.Multi.Screens.Match private readonly Participants participants; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); - private readonly Bindable roomBeatmap = new Bindable(); - - protected override Container TransitionContent => participants; + protected override Drawable TransitionContent => participants; public override string Title => room.Name.Value; @@ -41,6 +40,14 @@ namespace osu.Game.Screens.Multi.Screens.Match { this.room = room; + nameBind.BindTo(room.Name); + beatmapBind.BindTo(room.Beatmap); + statusBind.BindTo(room.Status); + availabilityBind.BindTo(room.Availability); + typeBind.BindTo(room.Type); + participantsBind.BindTo(room.Participants); + maxParticipantsBind.BindTo(room.MaxParticipants); + Header header; RoomSettingsOverlay settings; Info info; @@ -76,8 +83,6 @@ namespace osu.Game.Screens.Multi.Screens.Match header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect()); header.Beatmap.BindTo(Beatmap); - roomBeatmap.BindValueChanged(b => info.Beatmap = b, true); - header.Tabs.Current.ValueChanged += t => { if (t == MatchHeaderPage.Settings) @@ -94,31 +99,22 @@ namespace osu.Game.Screens.Multi.Screens.Match settings.Applied = () => settings.Hide(); - nameBind.BindTo(room.Name); - nameBind.BindValueChanged(n => info.Name = n, true); + info.Beatmap.BindTo(beatmapBind); + info.Name.BindTo(nameBind); + info.Status.BindTo(statusBind); + info.Availability.BindTo(availabilityBind); + info.Type.BindTo(typeBind); - statusBind.BindTo(room.Status); - statusBind.BindValueChanged(s => info.Status = s, true); - - availabilityBind.BindTo(room.Availability); - availabilityBind.BindValueChanged(a => info.Availability = a, true); - - typeBind.BindTo(room.Type); - typeBind.BindValueChanged(t => info.Type = t, true); - - maxParticipantsBind.BindTo(room.MaxParticipants); - maxParticipantsBind.BindValueChanged(m => { participants.Max = m; }, true); - - participantsBind.BindTo(room.Participants); - participantsBind.BindValueChanged(p => participants.Users = p, true); + participants.Users.BindTo(participantsBind); + participants.MaxParticipants.BindTo(maxParticipantsBind); } [BackgroundDependencyLoader] private void load() { - roomBeatmap.BindTo(room.Beatmap); - roomBeatmap.BindValueChanged(b => Beatmap.Value = beatmapManager.GetWorkingBeatmap(room.Beatmap.Value), true); - Beatmap.BindValueChanged(b => roomBeatmap.Value = b.BeatmapInfo); + beatmapBind.BindTo(room.Beatmap); + beatmapBind.BindValueChanged(b => Beatmap.Value = beatmapManager.GetWorkingBeatmap(room.Beatmap.Value), true); + Beatmap.BindValueChanged(b => beatmapBind.Value = b.BeatmapInfo); } } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Screens/Match/Participants.cs index a5ac93fffc..d40796760b 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Participants.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.SearchableList; @@ -12,35 +13,23 @@ using osuTK; namespace osu.Game.Screens.Multi.Screens.Match { - public class Participants : Container + public class Participants : CompositeDrawable { - private readonly ParticipantCount count; - private readonly FillFlowContainer usersFlow; + public readonly Bindable> Users = new Bindable>(); + public readonly Bindable MaxParticipants = new Bindable(); - public IEnumerable Users + public new MarginPadding Padding { - set - { - usersFlow.Children = value.Select(u => new UserPanel(u) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 300, - OnLoadComplete = d => d.FadeInFromZero(60), - }).ToList(); - - count.Count = value.Count(); - } - } - - public int? Max - { - set => count.Max = value; + get => base.Padding; + set => base.Padding = value; } public Participants() { - Child = new Container + FillFlowContainer usersFlow; + ParticipantCount count; + + InternalChild = new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, @@ -70,6 +59,21 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }, }; + + Users.BindValueChanged(v => + { + usersFlow.Children = v.Select(u => new UserPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 300, + OnLoadComplete = d => d.FadeInFromZero(60), + }).ToList(); + + count.Count = v.Count(); + }); + + MaxParticipants.BindValueChanged(v => count.Max = v); } } } diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs index fd866a5fef..3184316a33 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Graphics.Containers; @@ -10,7 +9,7 @@ namespace osu.Game.Screens.Multi.Screens { public abstract class MultiplayerScreen : OsuScreen, IMultiplayerScreen { - protected virtual Container TransitionContent => Content; + protected virtual Drawable TransitionContent => Content; public virtual string ShortTitle => Title; From 2a2561e5c89c4b19737fad567603bad60dd00fef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 19:39:54 +0900 Subject: [PATCH 089/355] Update framework and otehr nuget packages --- osu.Desktop/osu.Desktop.csproj | 4 ++-- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 4 ++-- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 11 +++++------ osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/Music/PlaylistItem.cs | 5 ++--- osu.Game/osu.Game.csproj | 8 ++++---- 10 files changed, 21 insertions(+), 23 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 09bfdc67d4..ab65541ecf 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -28,8 +28,8 @@ - - + + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index b76f591239..40f2375251 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 98ad086c66..12bf9759c4 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 6117812f45..3e06aab0e5 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 3ba64398f3..e0097bf9c3 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index c0f0695ff8..d45f1dd962 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -2,10 +2,10 @@ - + - + diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index de017baf35..2b0a49cb6c 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -15,20 +14,20 @@ using osuTK; namespace osu.Game.Online.Chat { /// - /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. + /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. /// public class DrawableLinkCompiler : OsuHoverContainer, IHasTooltip { /// /// Each word part of a chat link (split for word-wrap support). /// - public List Parts; + public List Parts; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parts.Any(d => d.ReceivePositionalInputAt(screenSpacePos)); protected override HoverClickSounds CreateHoverClickSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts); - public DrawableLinkCompiler(IEnumerable parts) + public DrawableLinkCompiler(IEnumerable parts) { Parts = parts.ToList(); } @@ -45,9 +44,9 @@ namespace osu.Game.Online.Chat private class LinkHoverSounds : HoverClickSounds { - private readonly List parts; + private readonly List parts; - public LinkHoverSounds(HoverSampleSet sampleSet, List parts) + public LinkHoverSounds(HoverSampleSet sampleSet, List parts) : base(sampleSet) { this.parts = parts; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cd40d4793a..73ecbafb9e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -553,9 +553,9 @@ namespace osu.Game try { - Logger.Log($"Loading {d}...", LoggingTarget.Debug); + Logger.Log($"Loading {d}...", level: LogLevel.Debug); await LoadComponentAsync(d, add); - Logger.Log($"Loaded {d}!", LoggingTarget.Debug); + Logger.Log($"Loaded {d}!", level: LogLevel.Debug); } catch (OperationCanceledException) { diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 5d89e53081..40a395535d 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -7,7 +7,6 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; @@ -26,7 +25,7 @@ namespace osu.Game.Overlays.Music private SpriteIcon handle; private TextFlowContainer text; - private IEnumerable titleSprites; + private IEnumerable titleSprites; private ILocalisedBindableString titleBind; private ILocalisedBindableString artistBind; @@ -58,7 +57,7 @@ namespace osu.Game.Overlays.Music selected = value; FinishTransforms(true); - foreach (SpriteText s in titleSprites) + foreach (Drawable s in titleSprites) s.FadeColour(Selected ? hoverColour : Color4.White, fade_duration); } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 85eabb0350..ed0e6c8417 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,11 +14,11 @@ - + - - - + + + From d379d0276115d66b422ee9bc249824ccb8d60fd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 20:12:56 +0900 Subject: [PATCH 090/355] Remove unnecessary base class --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 31 +++++++++++----------- osu.Game/Rulesets/Mods/ModBlinds.cs | 24 ----------------- 2 files changed, 16 insertions(+), 39 deletions(-) delete mode 100644 osu.Game/Rulesets/Mods/ModBlinds.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index a9379c9133..f216ae5814 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.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 System.Linq; +using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -9,30 +11,29 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModBlinds : ModBlinds + public class OsuModBlinds : Mod, IApplicableToRulesetContainer, IApplicableToScoreProcessor { + public override string Name => "Blinds"; + public override string Acronym => "BL"; + public override FontAwesome Icon => FontAwesome.fa_adjust; + public override ModType Type => ModType.DifficultyIncrease; + public override string Description => "Play with blinds on your screen."; + public override bool Ranked => false; + public override double ScoreMultiplier => 1.12; private DrawableOsuBlinds flashlight; - public override void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - bool hasEasy = false; - bool hasHardrock = false; - foreach (var mod in rulesetContainer.ActiveMods) - { - if (mod is ModEasy) - hasEasy = true; - if (mod is ModHardRock) - hasHardrock = true; - } + bool hasEasy = rulesetContainer.ActiveMods.Any(m => m is ModEasy); + bool hasHardrock = rulesetContainer.ActiveMods.Any(m => m is ModHardRock); + rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, hasEasy, hasHardrock, rulesetContainer.Beatmap)); } - public override void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.Health.ValueChanged += val => { - flashlight.AnimateTarget((float)val); - }; + scoreProcessor.Health.ValueChanged += val => { flashlight.AnimateTarget((float)val); }; } } } diff --git a/osu.Game/Rulesets/Mods/ModBlinds.cs b/osu.Game/Rulesets/Mods/ModBlinds.cs deleted file mode 100644 index e4a17551ec..0000000000 --- a/osu.Game/Rulesets/Mods/ModBlinds.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Graphics; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; - -namespace osu.Game.Rulesets.Mods -{ - public abstract class ModBlinds : Mod, IApplicableToRulesetContainer, IApplicableToScoreProcessor - where T : HitObject - { - public override string Name => "Blinds"; - public override string Acronym => "BL"; - public override FontAwesome Icon => FontAwesome.fa_adjust; - public override ModType Type => ModType.DifficultyIncrease; - public override string Description => "Play with blinds on your screen."; - public override bool Ranked => false; - - public abstract void ApplyToRulesetContainer(RulesetContainer rulesetContainer); - public abstract void ApplyToScoreProcessor(ScoreProcessor scoreProcessor); - } -} From 7d9cdf6f81c41f4fa4b96111bebb2e70a9391fac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 20:13:03 +0900 Subject: [PATCH 091/355] Remove unnecessary private field --- osu.Game/Rulesets/UI/RulesetContainer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 72e32290e2..67bcb7581f 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -68,11 +68,10 @@ namespace osu.Game.Rulesets.UI /// public Playfield Playfield => playfield.Value; - private readonly Container overlays; /// /// Place to put drawables above hit objects but below UI. /// - public Container Overlays => overlays; + public readonly Container Overlays; /// /// The cursor provided by this . May be null if no cursor is provided. @@ -93,7 +92,7 @@ namespace osu.Game.Rulesets.UI { Ruleset = ruleset; playfield = new Lazy(CreatePlayfield); - overlays = new Container + Overlays = new Container { RelativeSizeAxes = Axes.Both, Width = 1, From feb1adb51db60553b75ad454eb0085f1742c00e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 7 Dec 2018 19:38:46 +0900 Subject: [PATCH 092/355] Use bindable propagation rather than properties --- .../Screens/Multi/Components/BeatmapTitle.cs | 42 +++++---- .../Multi/Components/BeatmapTypeInfo.cs | 65 +++++++------- .../Screens/Multi/Components/DrawableRoom.cs | 29 +++---- .../Screens/Multi/Components/ModeTypeInfo.cs | 85 +++++++------------ .../Multi/Components/ParticipantCount.cs | 76 ++++++++--------- .../Multi/Components/ParticipantInfo.cs | 41 +++++---- .../Screens/Multi/Components/RoomInspector.cs | 33 +++---- osu.Game/Screens/Multi/Screens/Match/Info.cs | 5 +- .../Multi/Screens/Match/Participants.cs | 7 +- 9 files changed, 177 insertions(+), 206 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index 6dc59f5cac..e3ef5eb401 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.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.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; @@ -9,7 +10,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Multi.Components { - public class BeatmapTitle : FillFlowContainer + public class BeatmapTitle : CompositeDrawable { private readonly OsuSpriteText beatmapTitle, beatmapDash, beatmapArtist; @@ -18,31 +19,25 @@ namespace osu.Game.Screens.Multi.Components set { beatmapTitle.TextSize = beatmapDash.TextSize = beatmapArtist.TextSize = value; } } - private BeatmapInfo beatmap; - - public BeatmapInfo Beatmap - { - set - { - if (value == beatmap) return; - beatmap = value; - - if (IsLoaded) - updateText(); - } - } + public readonly Bindable Beatmap = new Bindable(); public BeatmapTitle() { AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - Children = new[] + InternalChild = new FillFlowContainer { - beatmapTitle = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, - beatmapDash = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, - beatmapArtist = new OsuSpriteText { Font = @"Exo2.0-RegularItalic", }, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + beatmapTitle = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, + beatmapDash = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, + beatmapArtist = new OsuSpriteText { Font = @"Exo2.0-RegularItalic", }, + } }; + + Beatmap.BindValueChanged(v => updateText()); } protected override void LoadComplete() @@ -53,16 +48,19 @@ namespace osu.Game.Screens.Multi.Components private void updateText() { - if (beatmap == null) + if (!IsLoaded) + return; + + if (Beatmap.Value == null) { beatmapTitle.Text = "Changing map"; beatmapDash.Text = beatmapArtist.Text = string.Empty; } else { - beatmapTitle.Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)); + beatmapTitle.Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)); beatmapDash.Text = @" - "; - beatmapArtist.Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)); + beatmapArtist.Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)); } } } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index a22e171275..2bd7b19a0a 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -12,53 +13,55 @@ using osuTK; namespace osu.Game.Screens.Multi.Components { - public class BeatmapTypeInfo : FillFlowContainer + public class BeatmapTypeInfo : CompositeDrawable { - private readonly ModeTypeInfo modeTypeInfo; - private readonly BeatmapTitle beatmapTitle; private readonly OsuSpriteText beatmapAuthor; - public BeatmapInfo Beatmap - { - set - { - modeTypeInfo.Beatmap = beatmapTitle.Beatmap = value; - beatmapAuthor.Text = value == null ? string.Empty : $"mapped by {value.Metadata.Author}"; - } - } + public readonly Bindable Beatmap = new Bindable(); - public GameType Type - { - set { modeTypeInfo.Type = value; } - } + public readonly Bindable Type = new Bindable(); public BeatmapTypeInfo() { AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - LayoutDuration = 100; - Spacing = new Vector2(5f, 0f); - Children = new Drawable[] + BeatmapTitle beatmapTitle; + ModeTypeInfo modeTypeInfo; + + InternalChild = new FillFlowContainer { - modeTypeInfo = new ModeTypeInfo(), - new Container + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + LayoutDuration = 100, + Spacing = new Vector2(5, 0), + Children = new Drawable[] { - AutoSizeAxes = Axes.X, - Height = 30, - Margin = new MarginPadding { Left = 5 }, - Children = new Drawable[] + modeTypeInfo = new ModeTypeInfo(), + new Container { - beatmapTitle = new BeatmapTitle(), - beatmapAuthor = new OsuSpriteText + AutoSizeAxes = Axes.X, + Height = 30, + Margin = new MarginPadding { Left = 5 }, + Children = new Drawable[] { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - TextSize = 14, + beatmapTitle = new BeatmapTitle(), + beatmapAuthor = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + TextSize = 14, + }, }, }, - }, + } }; + + modeTypeInfo.Beatmap.BindTo(Beatmap); + modeTypeInfo.Type.BindTo(Type); + + beatmapTitle.Beatmap.BindTo(Beatmap); + + Beatmap.BindValueChanged(v => beatmapAuthor.Text = v == null ? string.Empty : $"mapped by {v.Metadata.Author}"); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 6bdc4c2f2d..43a9b6ad06 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -38,10 +38,10 @@ namespace osu.Game.Screens.Multi.Components private readonly Box selectionBox; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable roomBeatmap = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); private readonly Bindable beatmap = new Bindable(); @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Multi.Components { Box sideStrip; UpdateableBeatmapBackgroundSprite background; - OsuSpriteText name, status; + OsuSpriteText status; ParticipantInfo participantInfo; BeatmapTitle beatmapTitle; ModeTypeInfo modeTypeInfo; @@ -166,9 +166,10 @@ namespace osu.Game.Screens.Multi.Components Spacing = new Vector2(5f), Children = new Drawable[] { - name = new OsuSpriteText + new OsuSpriteText { TextSize = 18, + Current = nameBind }, participantInfo = new ParticipantInfo(), }, @@ -206,11 +207,6 @@ namespace osu.Game.Screens.Multi.Components }, }; - nameBind.ValueChanged += n => name.Text = n; - hostBind.ValueChanged += h => participantInfo.Host = h; - typeBind.ValueChanged += m => modeTypeInfo.Type = m; - participantsBind.ValueChanged += p => participantInfo.Participants = p; - statusBind.ValueChanged += s => { status.Text = s.Message; @@ -221,19 +217,22 @@ namespace osu.Game.Screens.Multi.Components background.Beatmap.BindTo(beatmap); - roomBeatmap.ValueChanged += b => - { - beatmap.Value = beatmaps.GetWorkingBeatmap(b); - beatmapTitle.Beatmap = b; - modeTypeInfo.Beatmap = b; - }; + beatmapBind.ValueChanged += b => beatmap.Value = beatmaps.GetWorkingBeatmap(b); nameBind.BindTo(Room.Name); hostBind.BindTo(Room.Host); statusBind.BindTo(Room.Status); typeBind.BindTo(Room.Type); - roomBeatmap.BindTo(Room.Beatmap); + beatmapBind.BindTo(Room.Beatmap); participantsBind.BindTo(Room.Participants); + + modeTypeInfo.Beatmap.BindTo(beatmapBind); + modeTypeInfo.Type.BindTo(typeBind); + + participantInfo.Host.BindTo(hostBind); + participantInfo.Participants.BindTo(participantsBind); + + beatmapTitle.Beatmap.BindTo(beatmapBind); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 95f0c2153d..87d150c5a4 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.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.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -10,74 +11,54 @@ using osuTK; namespace osu.Game.Screens.Multi.Components { - public class ModeTypeInfo : Container + public class ModeTypeInfo : CompositeDrawable { private const float height = 30; private const float transition_duration = 100; - private readonly Container rulesetContainer, gameTypeContainer; + private readonly Container rulesetContainer; - public BeatmapInfo Beatmap - { - set - { - if (value != null) - { - rulesetContainer.FadeIn(transition_duration); - rulesetContainer.Children = new[] - { - new DifficultyIcon(value) - { - Size = new Vector2(height), - }, - }; - } - else - { - rulesetContainer.FadeOut(transition_duration); - } - } - } - - public GameType Type - { - set - { - gameTypeContainer.Children = new[] - { - new DrawableGameType(value) - { - Size = new Vector2(height), - }, - }; - } - } + public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Type = new Bindable(); public ModeTypeInfo() { AutoSizeAxes = Axes.Both; - Children = new[] + Container gameTypeContainer; + + InternalChild = new FillFlowContainer { - new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + LayoutDuration = 100, + Children = new[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - LayoutDuration = 100, - Children = new[] + rulesetContainer = new Container { - rulesetContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, - gameTypeContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, + AutoSizeAxes = Axes.Both, + }, + gameTypeContainer = new Container + { + AutoSizeAxes = Axes.Both, }, }, }; + + Beatmap.BindValueChanged(updateBeatmap); + Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }); + } + + private void updateBeatmap(BeatmapInfo beatmap) + { + if (beatmap != null) + { + rulesetContainer.FadeIn(transition_duration); + rulesetContainer.Child = new DifficultyIcon(beatmap) { Size = new Vector2(height) }; + } + else + rulesetContainer.FadeOut(transition_duration); } } } diff --git a/osu.Game/Screens/Multi/Components/ParticipantCount.cs b/osu.Game/Screens/Multi/Components/ParticipantCount.cs index e7183cbd92..66f13ed683 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantCount.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantCount.cs @@ -1,69 +1,65 @@ // 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.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Users; namespace osu.Game.Screens.Multi.Components { - public class ParticipantCount : FillFlowContainer + public class ParticipantCount : CompositeDrawable { private const float text_size = 30; private const float transition_duration = 100; - private readonly OsuSpriteText count, slash, maxText; + private readonly OsuSpriteText slash, maxText; - public int Count - { - set => count.Text = value.ToString(); - } - - private int? max; - public int? Max - { - get => max; - set - { - if (value == max) return; - max = value; - - updateMax(); - } - } + public readonly Bindable> Participants = new Bindable>(); + public readonly Bindable MaxParticipants = new Bindable(); public ParticipantCount() { AutoSizeAxes = Axes.Both; - Direction = FillDirection.Horizontal; - LayoutDuration = transition_duration; - Children = new[] + OsuSpriteText count; + + InternalChild = new FillFlowContainer { - count = new OsuSpriteText + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + LayoutDuration = transition_duration, + Children = new[] { - TextSize = text_size, - Font = @"Exo2.0-Bold" - }, - slash = new OsuSpriteText - { - Text = @"/", - TextSize = text_size, - Font = @"Exo2.0-Light" - }, - maxText = new OsuSpriteText - { - TextSize = text_size, - Font = @"Exo2.0-Light" - }, + count = new OsuSpriteText + { + TextSize = text_size, + Font = @"Exo2.0-Bold" + }, + slash = new OsuSpriteText + { + Text = @"/", + TextSize = text_size, + Font = @"Exo2.0-Light" + }, + maxText = new OsuSpriteText + { + TextSize = text_size, + Font = @"Exo2.0-Light" + }, + } }; - updateMax(); + Participants.BindValueChanged(v => count.Text = v.Count().ToString()); + MaxParticipants.BindValueChanged(_ => updateMax(), true); } private void updateMax() { - if (Max == null) + if (MaxParticipants.Value == null) { slash.FadeOut(transition_duration); maxText.FadeOut(transition_duration); @@ -71,7 +67,7 @@ namespace osu.Game.Screens.Multi.Components else { slash.FadeIn(transition_duration); - maxText.Text = Max.ToString(); + maxText.Text = MaxParticipants.Value.ToString(); maxText.FadeIn(transition_duration); } } diff --git a/osu.Game/Screens/Multi/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Components/ParticipantInfo.cs index b1c77a04af..47aff3f200 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantInfo.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -16,36 +17,21 @@ namespace osu.Game.Screens.Multi.Components { public class ParticipantInfo : Container { - private readonly Container flagContainer; private readonly OsuSpriteText host; private readonly FillFlowContainer levelRangeContainer; - private readonly OsuSpriteText levelRangeLower; - private readonly OsuSpriteText levelRangeHigher; - public User Host - { - set - { - host.Text = value.Username; - flagContainer.Children = new[] { new DrawableFlag(value.Country) { RelativeSizeAxes = Axes.Both } }; - } - } - - public IEnumerable Participants - { - set - { - var ranks = value.Select(u => u.Statistics.Ranks.Global); - levelRangeLower.Text = ranks.Min().ToString(); - levelRangeHigher.Text = ranks.Max().ToString(); - } - } + public readonly Bindable Host = new Bindable(); + public readonly Bindable> Participants = new Bindable>(); public ParticipantInfo(string rankPrefix = null) { RelativeSizeAxes = Axes.X; Height = 15f; + OsuSpriteText levelRangeHigher; + OsuSpriteText levelRangeLower; + Container flagContainer; + Children = new Drawable[] { new FillFlowContainer @@ -133,6 +119,19 @@ namespace osu.Game.Screens.Multi.Components }, }, }; + + Host.BindValueChanged(v => + { + host.Text = v.Username; + flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; + }); + + Participants.BindValueChanged(v => + { + var ranks = v.Select(u => u.Statistics.Ranks.Global); + levelRangeLower.Text = ranks.Min().ToString(); + levelRangeHigher.Text = ranks.Max().ToString(); + }); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index b7dcb3c8fb..d282264ed6 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -29,10 +29,10 @@ namespace osu.Game.Screens.Multi.Components private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); - private readonly Bindable roomBeatmap = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Multi.Components hostBind.UnbindBindings(); statusBind.UnbindBindings(); typeBind.UnbindBindings(); - roomBeatmap.UnbindBindings(); + beatmapBind.UnbindBindings(); maxParticipantsBind.UnbindBindings(); participantsBind.UnbindBindings(); @@ -74,7 +74,7 @@ namespace osu.Game.Screens.Multi.Components hostBind.BindTo(room.Host); statusBind.BindTo(room.Status); typeBind.BindTo(room.Type); - roomBeatmap.BindTo(room.Beatmap); + beatmapBind.BindTo(room.Beatmap); maxParticipantsBind.BindTo(room.MaxParticipants); participantsBind.BindTo(room.Participants); } @@ -131,6 +131,7 @@ namespace osu.Game.Screens.Multi.Components Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, TextSize = 30, + Current = nameBind }, }, }, @@ -203,26 +204,20 @@ namespace osu.Game.Screens.Multi.Components }, }; - nameBind.ValueChanged += n => name.Text = n; - hostBind.ValueChanged += h => participantInfo.Host = h; - typeBind.ValueChanged += t => beatmapTypeInfo.Type = t; - maxParticipantsBind.ValueChanged += m => participantCount.Max = m; statusBind.ValueChanged += displayStatus; + beatmapBind.ValueChanged += b => beatmap.Value = beatmaps.GetWorkingBeatmap(b); + participantsBind.ValueChanged += p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); background.Beatmap.BindTo(beatmap); - roomBeatmap.ValueChanged += b => - { - beatmap.Value = beatmaps.GetWorkingBeatmap(b); - beatmapTypeInfo.Beatmap = b; - }; + participantInfo.Host.BindTo(hostBind); + participantInfo.Participants.BindTo(participantsBind); - participantsBind.ValueChanged += p => - { - participantCount.Count = p.Count(); - participantInfo.Participants = p; - participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); - }; + participantCount.Participants.BindTo(participantsBind); + participantCount.MaxParticipants.BindTo(maxParticipantsBind); + + beatmapTypeInfo.Type.BindTo(typeBind); + beatmapTypeInfo.Beatmap.BindTo(beatmapBind); updateState(); } @@ -265,7 +260,7 @@ namespace osu.Game.Screens.Multi.Components participantInfo.FadeIn(transition_duration); statusBind.TriggerChange(); - roomBeatmap.TriggerChange(); + beatmapBind.TriggerChange(); } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Screens/Match/Info.cs index fc6e84c38a..9600a878a6 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Info.cs @@ -99,10 +99,11 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }; + beatmapTypeInfo.Beatmap.BindTo(Beatmap); + beatmapTypeInfo.Type.BindTo(Type); + Availability.BindValueChanged(_ => updateAvailabilityStatus()); Status.BindValueChanged(_ => updateAvailabilityStatus()); - Beatmap.BindValueChanged(b => beatmapTypeInfo.Beatmap = b); - Type.BindValueChanged(t => beatmapTypeInfo.Type = t); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Screens/Match/Participants.cs index d40796760b..98ab758f81 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Participants.cs @@ -60,6 +60,9 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }; + count.Participants.BindTo(Users); + count.MaxParticipants.BindTo(MaxParticipants); + Users.BindValueChanged(v => { usersFlow.Children = v.Select(u => new UserPanel(u) @@ -69,11 +72,7 @@ namespace osu.Game.Screens.Multi.Screens.Match Width = 300, OnLoadComplete = d => d.FadeInFromZero(60), }).ToList(); - - count.Count = v.Count(); }); - - MaxParticipants.BindValueChanged(v => count.Max = v); } } } From 4f34d42b3372aea76d29a3a09e771fac1b6f2af7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Dec 2018 21:11:35 +0900 Subject: [PATCH 093/355] Major code refactors --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 222 +++++++++++++++- .../Objects/Drawables/DrawableOsuBlinds.cs | 243 ------------------ .../Drawables/Pieces/ModBlindsPanelSprite.cs | 26 -- 3 files changed, 217 insertions(+), 274 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs delete mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index f216ae5814..4078dce643 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -2,38 +2,250 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { public class OsuModBlinds : Mod, IApplicableToRulesetContainer, IApplicableToScoreProcessor { public override string Name => "Blinds"; + public override string Description => "Play with blinds on your screen."; public override string Acronym => "BL"; + public override FontAwesome Icon => FontAwesome.fa_adjust; public override ModType Type => ModType.DifficultyIncrease; - public override string Description => "Play with blinds on your screen."; + public override bool Ranked => false; public override double ScoreMultiplier => 1.12; - private DrawableOsuBlinds flashlight; + private DrawableOsuBlinds blinds; public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { bool hasEasy = rulesetContainer.ActiveMods.Any(m => m is ModEasy); bool hasHardrock = rulesetContainer.ActiveMods.Any(m => m is ModHardRock); - rulesetContainer.Overlays.Add(flashlight = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, hasEasy, hasHardrock, rulesetContainer.Beatmap)); + rulesetContainer.Overlays.Add(blinds = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, hasEasy, hasHardrock, rulesetContainer.Beatmap)); } public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.Health.ValueChanged += val => { flashlight.AnimateTarget((float)val); }; + scoreProcessor.Health.ValueChanged += val => { blinds.AnimateClosedness((float)val); }; + } + + /// + /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. + /// + public class DrawableOsuBlinds : Container + { + /// + /// Black background boxes behind blind panel textures. + /// + private Box blackBoxLeft, blackBoxRight; + + private Drawable panelLeft, panelRight, bgPanelLeft, bgPanelRight; + + private readonly Beatmap beatmap; + + /// + /// Value between 0 and 1 setting a maximum "closedness" for the blinds. + /// Useful for animating how far the blinds can be opened while keeping them at the original position if they are wider open than this. + /// + private const float target_clamp = 1; + + private readonly float targetBreakMultiplier = 0; + private readonly float easing = 1; + + private const float black_depth = 10; + private const float bg_panel_depth = 8; + private const float fg_panel_depth = 4; + + private readonly CompositeDrawable restrictTo; + private readonly bool modEasy, modHardrock; + + /// + /// + /// Percentage of playfield to extend blinds over. Basically moves the origin points where the blinds start. + /// + /// + /// -1 would mean the blinds always cover the whole screen no matter health. + /// 0 would mean the blinds will only ever be on the edge of the playfield on 0% health. + /// 1 would mean the blinds are fully outside the playfield on 50% health. + /// Infinity would mean the blinds are always outside the playfield except on 100% health. + /// + /// + private const float leniency = 0.1f; + + public DrawableOsuBlinds(CompositeDrawable restrictTo, bool hasEasy, bool hasHardrock, Beatmap beatmap) + { + this.restrictTo = restrictTo; + this.beatmap = beatmap; + + modEasy = hasEasy; + modHardrock = hasHardrock; + } + + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.Both; + + Children = new[] + { + blackBoxLeft = new Box + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Y, + Width = 0, + Height = 1, + Depth = black_depth + }, + blackBoxRight = new Box + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Y, + Width = 0, + Height = 1, + Depth = black_depth + }, + bgPanelLeft = new ModBlindsPanel + { + Origin = Anchor.TopRight, + Colour = Color4.Gray, + Depth = bg_panel_depth + 1 + }, + panelLeft = new ModBlindsPanel + { + Origin = Anchor.TopRight, + Depth = bg_panel_depth + }, + bgPanelRight = new ModBlindsPanel + { + Origin = Anchor.TopLeft, + Colour = Color4.Gray, + Depth = fg_panel_depth + 1 + }, + panelRight = new ModBlindsPanel + { + Origin = Anchor.TopLeft, + Depth = fg_panel_depth + }, + }; + } + + private float applyGap(float value) + { + const float easy_multiplier = 0.95f; + const float hardrock_multiplier = 1.1f; + + float multiplier = 1; + if (modEasy) + { + multiplier = easy_multiplier; + // TODO: include OD/CS + } + else if (modHardrock) + { + multiplier = hardrock_multiplier; + // TODO: include OD/CS + } + + return MathHelper.Clamp(value * multiplier, 0, target_clamp) * targetBreakMultiplier; + } + + private static float applyAdjustmentCurve(float value) + { + // lagrange polinominal for (0,0) (0.5,0.35) (1,1) should make a good curve + return 0.6f * value * value + 0.4f * value; + } + + protected override void Update() + { + float start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; + float end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; + + float rawWidth = end - start; + + start -= rawWidth * leniency * 0.5f; + end += rawWidth * leniency * 0.5f; + + float width = (end - start) * 0.5f * applyAdjustmentCurve(applyGap(easing)); + + // different values in case the playfield ever moves from center to somewhere else. + blackBoxLeft.Width = start + width; + blackBoxRight.Width = DrawWidth - end + width; + + panelLeft.X = start + width; + panelRight.X = end - width; + bgPanelLeft.X = start; + bgPanelRight.X = end; + } + + protected override void LoadComplete() + { + const float break_open_early = 500; + const float break_close_late = 250; + + base.LoadComplete(); + + var firstObj = beatmap.HitObjects[0]; + var startDelay = firstObj.StartTime - firstObj.TimePreempt; + + using (BeginAbsoluteSequence(startDelay + break_close_late, true)) + leaveBreak(); + + foreach (var breakInfo in beatmap.Breaks) + { + if (breakInfo.HasEffect) + { + using (BeginAbsoluteSequence(breakInfo.StartTime - break_open_early, true)) + { + enterBreak(); + using (BeginDelayedSequence(breakInfo.Duration + break_open_early + break_close_late, true)) + leaveBreak(); + } + } + } + } + + private void enterBreak() => this.TransformTo(nameof(targetBreakMultiplier), 0f, 1000, Easing.OutSine); + + private void leaveBreak() => this.TransformTo(nameof(targetBreakMultiplier), 1f, 2500, Easing.OutBounce); + + /// + /// 0 is open, 1 is closed. + /// + public void AnimateClosedness(float value) => this.TransformTo(nameof(easing), value, 200, Easing.OutQuint); + + public class ModBlindsPanel : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + InternalChild = new SkinnableDrawable("Play/osu/blinds-panel", s => new Sprite { Texture = textures.Get("Play/osu/blinds-panel") }) + { + RelativeSizeAxes = Axes.Both, + }; + } + } } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs deleted file mode 100644 index d06f1250d8..0000000000 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuBlinds.cs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Game.Beatmaps; -using osu.Game.Skinning; -using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Osu.Objects.Drawables -{ - /// - /// Element for the Blinds mod drawing 2 black boxes covering the whole screen which resize inside a restricted area with some leniency. - /// - public class DrawableOsuBlinds : Container - { - /// - /// Black background boxes behind blind panel textures. - /// - private Box blackBoxLeft, blackBoxRight; - private Sprite panelLeft, panelRight; - private Sprite bgPanelLeft, bgPanelRight; - - private readonly Beatmap beatmap; - - private ISkinSource skin; - - private float targetClamp = 1; - private readonly float targetBreakMultiplier = 0; - private float target = 1; - private readonly float easing = 1; - - private const float black_depth = 10; - private const float bg_panel_depth = 8; - private const float fg_panel_depth = 4; - - private readonly CompositeDrawable restrictTo; - private readonly bool modEasy, modHardrock; - - /// - /// - /// Percentage of playfield to extend blinds over. Basically moves the origin points where the blinds start. - /// - /// - /// -1 would mean the blinds always cover the whole screen no matter health. - /// 0 would mean the blinds will only ever be on the edge of the playfield on 0% health. - /// 1 would mean the blinds are fully outside the playfield on 50% health. - /// Infinity would mean the blinds are always outside the playfield except on 100% health. - /// - /// - private const float leniency = 0.1f; - - public DrawableOsuBlinds(CompositeDrawable restrictTo, bool hasEasy, bool hasHardrock, Beatmap beatmap) - { - this.restrictTo = restrictTo; - this.beatmap = beatmap; - - modEasy = hasEasy; - modHardrock = hasHardrock; - } - - [BackgroundDependencyLoader] - private void load(ISkinSource skin, TextureStore textures) - { - RelativeSizeAxes = Axes.Both; - Width = 1; - Height = 1; - - Add(blackBoxLeft = new Box - { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - Colour = Color4.Black, - RelativeSizeAxes = Axes.Y, - Width = 0, - Height = 1, - Depth = black_depth - }); - Add(blackBoxRight = new Box - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Colour = Color4.Black, - RelativeSizeAxes = Axes.Y, - Width = 0, - Height = 1, - Depth = black_depth - }); - - Add(bgPanelLeft = new ModBlindsPanelSprite { - Origin = Anchor.TopRight, - Colour = Color4.Gray, - Depth = bg_panel_depth + 1 - }); - Add(panelLeft = new ModBlindsPanelSprite { - Origin = Anchor.TopRight, - Depth = bg_panel_depth - }); - - Add(bgPanelRight = new ModBlindsPanelSprite { - Origin = Anchor.TopLeft, - Colour = Color4.Gray, - Depth = fg_panel_depth + 1 - }); - Add(panelRight = new ModBlindsPanelSprite { - Origin = Anchor.TopLeft, - Depth = fg_panel_depth - }); - - this.skin = skin; - skin.SourceChanged += skinChanged; - PanelTexture = textures.Get("Play/osu/blinds-panel"); - } - - private void skinChanged() - { - PanelTexture = skin.GetTexture("Play/osu/blinds-panel"); - } - - private float applyGap(float value) - { - const float easy_multiplier = 0.95f; - const float hardrock_multiplier = 1.1f; - - float multiplier = 1; - if (modEasy) - { - multiplier = easy_multiplier; - // TODO: include OD/CS - } - else if (modHardrock) - { - multiplier = hardrock_multiplier; - // TODO: include OD/CS - } - - return MathHelper.Clamp(value * multiplier, 0, targetClamp) * targetBreakMultiplier; - } - - private static float applyAdjustmentCurve(float value) - { - // lagrange polinominal for (0,0) (0.5,0.35) (1,1) should make a good curve - return 0.6f * value * value + 0.4f * value; - } - - protected override void Update() - { - float start = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopLeft).X; - float end = Parent.ToLocalSpace(restrictTo.ScreenSpaceDrawQuad.TopRight).X; - float rawWidth = end - start; - start -= rawWidth * leniency * 0.5f; - end += rawWidth * leniency * 0.5f; - - float width = (end - start) * 0.5f * applyAdjustmentCurve(applyGap(easing)); - // different values in case the playfield ever moves from center to somewhere else. - blackBoxLeft.Width = start + width; - blackBoxRight.Width = DrawWidth - end + width; - - panelLeft.X = start + width; - panelRight.X = end - width; - bgPanelLeft.X = start; - bgPanelRight.X = end; - } - - protected override void LoadComplete() - { - const float break_open_early = 500; - const float break_close_late = 250; - - base.LoadComplete(); - - var firstObj = beatmap.HitObjects[0]; - var startDelay = firstObj.StartTime - firstObj.TimePreempt; - - using (BeginAbsoluteSequence(startDelay + break_close_late, true)) - LeaveBreak(); - - foreach (var breakInfo in beatmap.Breaks) - { - if (breakInfo.HasEffect) - { - using (BeginAbsoluteSequence(breakInfo.StartTime - break_open_early, true)) - { - EnterBreak(); - using (BeginDelayedSequence(breakInfo.Duration + break_open_early + break_close_late, true)) - LeaveBreak(); - } - } - } - } - - public void EnterBreak() - { - this.TransformTo(nameof(targetBreakMultiplier), 0f, 1000, Easing.OutSine); - } - - public void LeaveBreak() - { - this.TransformTo(nameof(targetBreakMultiplier), 1f, 2500, Easing.OutBounce); - } - - /// - /// Value between 0 and 1 setting a maximum "closedness" for the blinds. - /// Useful for animating how far the blinds can be opened while keeping them at the original position if they are wider open than this. - /// - public float TargetClamp - { - get => targetClamp; - set => targetClamp = value; - } - - /// - /// Health between 0 and 1 for the blinds to base the width on. Will get animated for 200ms using out-quintic easing. - /// - public void AnimateTarget(float value) - { - target = value; - this.TransformTo(nameof(easing), target, 200, Easing.OutQuint); - } - - public float Target - { - get => target; - } - - public Texture PanelTexture - { - set - { - panelLeft.Texture = value; - panelRight.Texture = value; - bgPanelLeft.Texture = value; - bgPanelRight.Texture = value; - } - } - } -} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs deleted file mode 100644 index c6e2db1842..0000000000 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ModBlindsPanelSprite.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; - -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces -{ - public class ModBlindsPanelSprite : Sprite - { - public ModBlindsPanelSprite() - { - RelativeSizeAxes = Axes.None; - Anchor = Anchor.TopLeft; - } - - protected override void Update() - { - Height = Parent?.DrawHeight ?? 0; - if (Height == 0 || Texture == null) - Width = 0; - else - Width = Texture.Width / (float)Texture.Height * Height; - } - } -} From 7a703f923799f403e2bb98ade1868d1a8fb3bc6b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Dec 2018 15:08:25 +0900 Subject: [PATCH 094/355] Fix API getting stuck in connecting state on some exceptions --- osu.Game/Online/API/APIAccess.cs | 48 ++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 1dda257c95..cf709e2162 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -196,19 +196,7 @@ namespace osu.Game.Online.API /// true if we should remove this request from the queue. private bool handleRequest(APIRequest req) { - try - { - Logger.Log($@"Performing request {req}", LoggingTarget.Network); - req.Perform(this); - - //we could still be in initialisation, at which point we don't want to say we're Online yet. - if (IsLoggedIn) - State = APIState.Online; - - failureCount = 0; - return true; - } - catch (WebException we) + bool handleWebException(WebException we) { HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); @@ -217,6 +205,7 @@ namespace osu.Game.Online.API switch (we.Message) { case "Unauthorized": + case "Forbidden": statusCode = HttpStatusCode.Unauthorized; break; } @@ -239,9 +228,40 @@ namespace osu.Game.Online.API return true; } - req.Fail(we); return true; } + + try + { + Logger.Log($@"Performing request {req}", LoggingTarget.Network); + req.Failure += ex => + { + switch (ex) + { + case WebException we: + handleWebException(we); + break; + } + }; + + req.Perform(this); + + //we could still be in initialisation, at which point we don't want to say we're Online yet. + if (IsLoggedIn) + State = APIState.Online; + + failureCount = 0; + return true; + } + catch (WebException we) + { + var removeFromQueue = handleWebException(we); + + if (removeFromQueue) + req.Fail(we); + + return removeFromQueue; + } catch (Exception e) { if (e is TimeoutException) From 784a114eae0b117c2daacf2081ba4ebdf34c6379 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Sun, 9 Dec 2018 23:38:19 +0700 Subject: [PATCH 095/355] formatting fix Co-Authored-By: pavlukivan --- osu.Game/Rulesets/Objects/HitWindows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 621fb418eb..76d6579fc6 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Objects { timeOffset = Math.Abs(timeOffset); - for(var result = HitResult.Perfect; result >= HitResult.Miss; --result) + for (var result = HitResult.Perfect; result >= HitResult.Miss; --result) { if(IsHitResultAllowed(result) && timeOffset <= HalfWindowFor(result)) return result; From 77a544e475360e72446d97c9f7b5a74678eb3906 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Sun, 9 Dec 2018 23:38:29 +0700 Subject: [PATCH 096/355] formatting fix Co-Authored-By: pavlukivan --- osu.Game/Rulesets/Objects/HitWindows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 76d6579fc6..319bfdec65 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Objects for (var result = HitResult.Perfect; result >= HitResult.Miss; --result) { - if(IsHitResultAllowed(result) && timeOffset <= HalfWindowFor(result)) + if (IsHitResultAllowed(result) && timeOffset <= HalfWindowFor(result)) return result; } From 8457324044641bde7650f125f8fd018f508ec2a9 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Mon, 10 Dec 2018 09:04:12 +0700 Subject: [PATCH 097/355] SuccessfulHitWindow->SuccessfulHitResult --- osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs | 2 +- .../Scoring/TaikoScoreProcessor.cs | 13 ++++++++++--- osu.Game/Rulesets/Objects/HitWindows.cs | 6 +++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index 722a327f45..2317d4cc90 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Objects { HitResult.Miss, (270, 190, 140) }, }; - protected override double SuccessfulHitWindow => Good; + protected override HitResult SuccessfulHitResult => HitResult.Good; public override bool IsHitResultAllowed(HitResult result) { diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 058d2b4beb..bd92905648 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -12,16 +12,23 @@ namespace osu.Game.Rulesets.Taiko.Scoring internal class TaikoScoreProcessor : ScoreProcessor { /// - /// The HP awarded by a hit. + /// A value used in calculating . /// - private const double hp_hit_great = 0.03; + private const double object_count_factor = 3; /// /// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; + /// + /// HP multiplier for a successful . + /// private double hpMultiplier; + + /// + /// HP multiplier for a . + /// private double hpMissMultiplier; public TaikoScoreProcessor(RulesetContainer rulesetContainer) @@ -33,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring { base.ApplyBeatmap(beatmap); - hpMultiplier = 0.01 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); + hpMultiplier = 1 / (object_count_factor * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120); } diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 319bfdec65..dd114afb7b 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -51,9 +51,9 @@ namespace osu.Game.Rulesets.Objects public double Miss { get; protected set; } /// - /// Hit window for a non- result. + /// The with the largest hit window that produces a successful hit. /// - protected virtual double SuccessfulHitWindow => Meh; + protected virtual HitResult SuccessfulHitResult => HitResult.Meh; /// /// Whether it's possible to achieve this . @@ -136,6 +136,6 @@ namespace osu.Game.Rulesets.Objects /// /// The time offset. /// Whether the can be hit at any point in the future from this time offset. - public bool CanBeHit(double timeOffset) => timeOffset <= SuccessfulHitWindow / 2; + public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(SuccessfulHitResult); } } From 352a758f5ce14f4c6cdf9198b6e6a79948538939 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 13:18:03 +0900 Subject: [PATCH 098/355] Replace 3 occurrences of SpriteText.Current --- osu.Game/Screens/Multi/Components/DrawableRoom.cs | 10 ++++------ osu.Game/Screens/Multi/Components/RoomInspector.cs | 9 +++++---- osu.Game/Screens/Multi/Screens/Match/Info.cs | 13 ++++--------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index 43a9b6ad06..9425457670 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -108,6 +108,7 @@ namespace osu.Game.Screens.Multi.Components ParticipantInfo participantInfo; BeatmapTitle beatmapTitle; ModeTypeInfo modeTypeInfo; + OsuSpriteText name; Children = new Drawable[] { @@ -166,11 +167,7 @@ namespace osu.Game.Screens.Multi.Components Spacing = new Vector2(5f), Children = new Drawable[] { - new OsuSpriteText - { - TextSize = 18, - Current = nameBind - }, + name = new OsuSpriteText { TextSize = 18 }, participantInfo = new ParticipantInfo(), }, }, @@ -217,7 +214,8 @@ namespace osu.Game.Screens.Multi.Components background.Beatmap.BindTo(beatmap); - beatmapBind.ValueChanged += b => beatmap.Value = beatmaps.GetWorkingBeatmap(b); + beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); + nameBind.BindValueChanged(n => name.Text = n); nameBind.BindTo(Room.Name); hostBind.BindTo(Room.Host); diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index d282264ed6..48d1c1b93c 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -131,7 +131,6 @@ namespace osu.Game.Screens.Multi.Components Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, TextSize = 30, - Current = nameBind }, }, }, @@ -204,9 +203,11 @@ namespace osu.Game.Screens.Multi.Components }, }; - statusBind.ValueChanged += displayStatus; - beatmapBind.ValueChanged += b => beatmap.Value = beatmaps.GetWorkingBeatmap(b); - participantsBind.ValueChanged += p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); + statusBind.BindValueChanged(displayStatus); + beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); + participantsBind.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); + + nameBind.BindValueChanged(n => name.Text = n); background.Beatmap.BindTo(beatmap); diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Screens/Match/Info.cs index 9600a878a6..d479765159 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Info.cs @@ -42,6 +42,7 @@ namespace osu.Game.Screens.Multi.Screens.Match Height = HEIGHT; BeatmapTypeInfo beatmapTypeInfo; + OsuSpriteText name; Children = new Drawable[] { @@ -69,15 +70,8 @@ namespace osu.Game.Screens.Multi.Screens.Match Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuSpriteText - { - TextSize = 30, - Current = Name - }, - availabilityStatus = new OsuSpriteText - { - TextSize = 14, - }, + name = new OsuSpriteText { TextSize = 30 }, + availabilityStatus = new OsuSpriteText { TextSize = 14 }, }, }, beatmapTypeInfo = new BeatmapTypeInfo @@ -104,6 +98,7 @@ namespace osu.Game.Screens.Multi.Screens.Match Availability.BindValueChanged(_ => updateAvailabilityStatus()); Status.BindValueChanged(_ => updateAvailabilityStatus()); + Name.BindValueChanged(n => name.Text = n); } [BackgroundDependencyLoader] From 41c7d10dff8edad5407d64689d6c5b678b3e93e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 13:48:05 +0900 Subject: [PATCH 099/355] Fix compilation issues (+ use updated framework) --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 2 +- osu.Game/OsuGame.cs | 4 ++-- osu.Game/Overlays/Music/PlaylistItem.cs | 3 ++- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 54a2ea47f9..795fe7caf4 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -62,7 +62,7 @@ namespace osu.Game.Graphics.Containers public void AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) { - AddInternal(new DrawableLinkCompiler(AddText(text, creationParameters).ToList()) + AddInternal(new DrawableLinkCompiler(AddText(text, creationParameters).OfType().ToList()) { TooltipText = tooltipText ?? (url != text ? url : string.Empty), Action = () => diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cd40d4793a..73ecbafb9e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -553,9 +553,9 @@ namespace osu.Game try { - Logger.Log($"Loading {d}...", LoggingTarget.Debug); + Logger.Log($"Loading {d}...", level: LogLevel.Debug); await LoadComponentAsync(d, add); - Logger.Log($"Loaded {d}!", LoggingTarget.Debug); + Logger.Log($"Loaded {d}!", level: LogLevel.Debug); } catch (OperationCanceledException) { diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 5d89e53081..2f5bcd129a 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -111,7 +112,7 @@ namespace osu.Game.Overlays.Music { sprite.TextSize = 16; sprite.Font = @"Exo2.0-Regular"; - }); + }).OfType(); text.AddText(artistBind.Value, sprite => { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a1578b6eb8..cdb94d6ab7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From be3a912d0be20e372a7d01c52cb57168ed0f4c5e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 13:48:10 +0900 Subject: [PATCH 100/355] Use UnbindFrom() --- .../Screens/Multi/Components/RoomInspector.cs | 25 +++++++++++-------- .../Multi/Components/RoomSettingsOverlay.cs | 13 ++++++---- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index 48d1c1b93c..07cf5541c5 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.cs @@ -54,19 +54,24 @@ namespace osu.Game.Screens.Multi.Components private Room room; public Room Room { - get { return room; } + get => room; set { - if (value == room) return; - room = value; + if (value == room) + return; - nameBind.UnbindBindings(); - hostBind.UnbindBindings(); - statusBind.UnbindBindings(); - typeBind.UnbindBindings(); - beatmapBind.UnbindBindings(); - maxParticipantsBind.UnbindBindings(); - participantsBind.UnbindBindings(); + if (room != null) + { + nameBind.UnbindFrom(room.Name); + hostBind.UnbindFrom(room.Host); + statusBind.UnbindFrom(room.Status); + typeBind.UnbindFrom(room.Type); + beatmapBind.UnbindFrom(room.Beatmap); + maxParticipantsBind.UnbindFrom(room.MaxParticipants); + participantsBind.UnbindFrom(room.Participants); + } + + room = value; if (room != null) { diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index bd9b269452..92a8fc8bb7 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -190,12 +190,15 @@ namespace osu.Game.Screens.Multi.Components if (room == value) return; - room = value; + if (room != null) + { + nameBind.UnbindFrom(room.Name); + availabilityBind.UnbindFrom(room.Availability); + typeBind.UnbindFrom(room.Type); + maxParticipantsBind.UnbindFrom(room.MaxParticipants); + } - nameBind.UnbindBindings(); - availabilityBind.UnbindBindings(); - typeBind.UnbindBindings(); - maxParticipantsBind.UnbindBindings(); + room = value; if (room != null) { From 839e177d2a6a6ab84446cdce32051595892c4115 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Mon, 10 Dec 2018 04:59:35 +0000 Subject: [PATCH 101/355] Docstring change --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index bd92905648..318efdbf3e 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring internal class TaikoScoreProcessor : ScoreProcessor { /// - /// A value used in calculating . + /// A value used for calculating . /// private const double object_count_factor = 3; From a2d1c2c096ccfbc56ceff2319164393dd4e2c149 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Mon, 10 Dec 2018 05:05:03 +0000 Subject: [PATCH 102/355] Fix formatting --- osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index 7c525bba6c..024e0e618f 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements protected override double HealthIncreaseFor(HitResult result) { - switch(result) + switch (result) { case HitResult.Miss: return -0.65; From a62b105fb539c9a52e4e09f3f937652cab4dbe8f Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Mon, 10 Dec 2018 05:06:18 +0000 Subject: [PATCH 103/355] Fix formatting --- osu.Game/Rulesets/Objects/HitWindows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index dd114afb7b..e4d987e2dc 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Objects /// The result. public virtual bool IsHitResultAllowed(HitResult result) { - switch(result) + switch (result) { case HitResult.Perfect: case HitResult.Ok: From c7970e54253415692b1a474da96f483abbec1aae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 16:50:00 +0900 Subject: [PATCH 104/355] Cleanup handling of readonly fields --- .../Multi/Components/DisableableTabControl.cs | 26 +++++------ .../Multi/Components/RoomSettingsOverlay.cs | 44 ++++++++++--------- .../Lounge}/CreateRoomOverlay.cs | 11 ++++- osu.Game/Screens/Multi/Screens/Match/Match.cs | 3 +- 4 files changed, 49 insertions(+), 35 deletions(-) rename osu.Game/Screens/Multi/{Components => Screens/Lounge}/CreateRoomOverlay.cs (69%) diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs index 1ca61a2678..e2a44f7ff4 100644 --- a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.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 System.Collections.Generic; +using osu.Framework.Configuration; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -9,33 +9,33 @@ namespace osu.Game.Screens.Multi.Components { public abstract class DisableableTabControl : TabControl { - public IEnumerable DisabledItems + public readonly BindableBool ReadOnly = new BindableBool(); + + protected override void AddTabItem(TabItem tab, bool addToDropdown = true) { - set - { - foreach (var item in value) - (TabMap[item] as DisableableTabItem)?.Disable(); - } + if (tab is DisableableTabItem disableable) + disableable.ReadOnly.BindTo(ReadOnly); + base.AddTabItem(tab, addToDropdown); } protected abstract class DisableableTabItem : TabItem { + public readonly BindableBool ReadOnly = new BindableBool(); + protected DisableableTabItem(T value) : base(value) { + ReadOnly.BindValueChanged(updateReadOnly); } - private bool isDisabled; - - public void Disable() + private void updateReadOnly(bool readOnly) { - Alpha = 0.2f; - isDisabled = true; + Alpha = readOnly ? 0.2f : 1; } protected override bool OnClick(ClickEvent e) { - if (isDisabled) + if (ReadOnly) return true; return base.OnClick(e); } diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs index 92a8fc8bb7..4e0a9ff3a2 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs @@ -40,6 +40,7 @@ namespace osu.Game.Screens.Multi.Components protected readonly RoomAvailabilityPicker AvailabilityPicker; protected readonly GameTypePicker TypePicker; protected readonly TriangleButton ApplyButton; + protected readonly OsuPasswordTextBox PasswordField; public RoomSettingsOverlay() { @@ -116,20 +117,16 @@ namespace osu.Game.Screens.Multi.Components { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, - Alpha = 0.2f, - ReadOnly = true, OnCommit = (sender, text) => apply(), }, }, new Section("PASSWORD (OPTIONAL)") { - Child = new SettingsPasswordTextBox + Child = PasswordField = new SettingsPasswordTextBox { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), - Alpha = 0.2f, - ReadOnly = true, + OnCommit = (sender, text) => apply() }, }, }, @@ -154,20 +151,6 @@ namespace osu.Game.Screens.Multi.Components typeBind.ValueChanged += t => TypePicker.Current.Value = t; maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); - AvailabilityPicker.DisabledItems = new[] - { - RoomAvailability.FriendsOnly, - RoomAvailability.InviteOnly - }; - - TypePicker.DisabledItems = new GameType[] - { - new GameTypeTag(), - new GameTypeVersus(), - new GameTypeTagTeam(), - new GameTypeTeamVersus(), - }; - Room = new Room(); } @@ -177,6 +160,27 @@ namespace osu.Game.Screens.Multi.Components typeLabel.Colour = colours.Yellow; } + private bool readOnly; + + public bool ReadOnly + { + get => readOnly; + set + { + if (readOnly == value) + return; + readOnly = value; + + NameField.ReadOnly = value; + MaxParticipantsField.ReadOnly = value; + PasswordField.ReadOnly = value; + AvailabilityPicker.ReadOnly.Value = value; + TypePicker.ReadOnly.Value = value; + ApplyButton.Enabled.Value = !value; + } + } + + private Room room; /// diff --git a/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs b/osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs similarity index 69% rename from osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs rename to osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs index 3a6224da26..45acb7ebec 100644 --- a/osu.Game/Screens/Multi/Components/CreateRoomOverlay.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs @@ -4,14 +4,23 @@ using osu.Framework.Allocation; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Screens.Lounge { public class CreateRoomOverlay : RoomSettingsOverlay { [Resolved] private APIAccess api { get; set; } + public CreateRoomOverlay() + { + MaxParticipantsField.ReadOnly = true; + AvailabilityPicker.ReadOnly.Value = true; + TypePicker.ReadOnly.Value = true; + PasswordField.ReadOnly = true; + } + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 4f81ffd305..74e5bf0a85 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -75,7 +75,8 @@ namespace osu.Game.Screens.Multi.Screens.Match { RelativeSizeAxes = Axes.Both, Height = 0.9f, - Room = room + Room = room, + ReadOnly = true }, }, }; From 3b688c702c5cfd82b4c1e0a5b968d0aac844113e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 17:06:34 +0900 Subject: [PATCH 105/355] Use graying rather than alpha --- osu.Game/Screens/Multi/Components/DisableableTabControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs index e2a44f7ff4..fdc2fd578d 100644 --- a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -4,6 +4,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osuTK.Graphics; namespace osu.Game.Screens.Multi.Components { @@ -30,7 +31,7 @@ namespace osu.Game.Screens.Multi.Components private void updateReadOnly(bool readOnly) { - Alpha = readOnly ? 0.2f : 1; + Colour = readOnly ? Color4.Gray : Color4.White; } protected override bool OnClick(ClickEvent e) From 77193eeea4b925caee2e0bd96d347222f655f1df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 18:00:57 +0900 Subject: [PATCH 106/355] Move from lobby into match for creation process --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 1 + osu.Game/Online/Multiplayer/Room.cs | 2 + .../Multi/Screens/Lounge/CreateRoomOverlay.cs | 42 ------------ .../Screens/Multi/Screens/Lounge/Lounge.cs | 22 ++---- .../Screens/Multi/Screens/Match/Header.cs | 7 +- osu.Game/Screens/Multi/Screens/Match/Match.cs | 16 +++-- .../Screens/Multi/Screens/Match/MatchPage.cs | 28 ++++++++ .../Multi/Screens/Match/MatchTabControl.cs | 68 +++++++++++++++++++ .../Match}/RoomSettingsOverlay.cs | 3 +- 9 files changed, 119 insertions(+), 70 deletions(-) delete mode 100644 osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs create mode 100644 osu.Game/Screens/Multi/Screens/Match/MatchPage.cs create mode 100644 osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs rename osu.Game/Screens/Multi/{Components => Screens/Match}/RoomSettingsOverlay.cs (99%) diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index 463002fbcb..b0b287fdb3 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing.Input; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Multi.Screens.Match; using osuTK.Input; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 8395b7e638..67ddb60823 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -19,5 +19,7 @@ namespace osu.Game.Online.Multiplayer public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(Enumerable.Empty()); + + public Bindable Created = new Bindable(); } } diff --git a/osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs b/osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs deleted file mode 100644 index 45acb7ebec..0000000000 --- a/osu.Game/Screens/Multi/Screens/Lounge/CreateRoomOverlay.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Game.Online.API; -using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Components; - -namespace osu.Game.Screens.Multi.Screens.Lounge -{ - public class CreateRoomOverlay : RoomSettingsOverlay - { - [Resolved] - private APIAccess api { get; set; } - - public CreateRoomOverlay() - { - MaxParticipantsField.ReadOnly = true; - AvailabilityPicker.ReadOnly.Value = true; - TypePicker.ReadOnly.Value = true; - PasswordField.ReadOnly = true; - } - - [BackgroundDependencyLoader] - private void load() - { - Room.Host.Value = api.LocalUser; - } - - public override Room Room - { - get => base.Room; - set - { - base.Room = value; - - if (api != null && value != null) - value.Host.Value = api.LocalUser; - } - } - } -} diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 140b3550c1..6fa254be05 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -19,7 +19,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { private readonly Container content; private readonly SearchContainer search; - private readonly CreateRoomOverlay createRoomOverlay; protected readonly FilterControl Filter; protected readonly FillFlowContainer RoomsContainer; @@ -68,16 +67,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge RelativeSizeAxes = Axes.Both, Width = 0.45f, }, - new Container - { - RelativeSizeAxes = Axes.Both, - Child = createRoomOverlay = new CreateRoomOverlay - { - RelativeSizeAxes = Axes.Both, - Height = 0.9f, - Room = new Room() - }, - }, }, } }; @@ -85,8 +74,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; - - createRoomOverlay.Applied = () => createRoom(createRoomOverlay.Room); } protected override void UpdateAfterChildren() @@ -147,8 +134,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { base.OnResuming(last); - createRoomOverlay.Room = new Room(); - Filter.Search.HoldFocus = true; } @@ -161,9 +146,10 @@ namespace osu.Game.Screens.Multi.Screens.Lounge private void filterRooms() { if (Filter.Tabs.Current.Value == LoungeTab.Create) - createRoomOverlay.Show(); - else - createRoomOverlay.Hide(); + { + Filter.Tabs.Current.Value = LoungeTab.Public; + createRoom(new Room()); + } search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index 50db63e3e3..78a4a937a4 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -29,7 +28,7 @@ namespace osu.Game.Screens.Multi.Screens.Match private readonly Box tabStrip; - public readonly PageTabControl Tabs; + public readonly MatchTabControl Tabs; public Action OnRequestSelectBeatmap; @@ -78,11 +77,11 @@ namespace osu.Game.Screens.Multi.Screens.Match RelativeSizeAxes = Axes.Both, }, }, - Tabs = new PageTabControl + Tabs = new MatchTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, + RelativeSizeAxes = Axes.X }, }, }, diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 74e5bf0a85..f444cb4073 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -7,8 +7,8 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Select; using osu.Game.Users; @@ -16,7 +16,6 @@ namespace osu.Game.Screens.Multi.Screens.Match { public class Match : MultiplayerScreen { - private readonly Room room; private readonly Participants participants; private readonly Bindable nameBind = new Bindable(); @@ -33,9 +32,17 @@ namespace osu.Game.Screens.Multi.Screens.Match public override string ShortTitle => "room"; + private readonly Header header; + + [Cached] + private readonly Room room; + [Resolved] private BeatmapManager beatmapManager { get; set; } + [Resolved] + private APIAccess api { get; set; } + public Match(Room room) { this.room = room; @@ -48,7 +55,6 @@ namespace osu.Game.Screens.Multi.Screens.Match participantsBind.BindTo(room.Participants); maxParticipantsBind.BindTo(room.MaxParticipants); - Header header; RoomSettingsOverlay settings; Info info; @@ -86,7 +92,7 @@ namespace osu.Game.Screens.Multi.Screens.Match header.Tabs.Current.ValueChanged += t => { - if (t == MatchHeaderPage.Settings) + if (t is SettingsMatchPage) settings.Show(); else settings.Hide(); @@ -95,7 +101,7 @@ namespace osu.Game.Screens.Multi.Screens.Match settings.StateChanged += s => { if (s == Visibility.Hidden) - header.Tabs.Current.Value = MatchHeaderPage.Room; + header.Tabs.Current.Value = new RoomMatchPage(); }; settings.Applied = () => settings.Hide(); diff --git a/osu.Game/Screens/Multi/Screens/Match/MatchPage.cs b/osu.Game/Screens/Multi/Screens/Match/MatchPage.cs new file mode 100644 index 0000000000..710e41ec69 --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Match/MatchPage.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; + +namespace osu.Game.Screens.Multi.Screens.Match +{ + public abstract class MatchPage + { + public abstract string Name { get; } + + public readonly BindableBool Enabled = new BindableBool(true); + + public override string ToString() => Name; + public override int GetHashCode() => GetType().GetHashCode(); + public override bool Equals(object obj) => GetType() == obj?.GetType(); + } + + public class SettingsMatchPage : MatchPage + { + public override string Name => "Settings"; + } + + public class RoomMatchPage : MatchPage + { + public override string Name => "Room"; + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs b/osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs new file mode 100644 index 0000000000..5fd64179cd --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osuTK.Graphics; + +namespace osu.Game.Screens.Multi.Screens.Match +{ + public class MatchTabControl : PageTabControl + { + private readonly IBindable created = new Bindable(); + + [Resolved] + private Room room { get; set; } + + public MatchTabControl() + { + AddItem(new SettingsMatchPage()); + AddItem(new RoomMatchPage()); + } + + [BackgroundDependencyLoader] + private void load() + { + created.BindTo(room.Created); + created.BindValueChanged(v => + { + if (v) + { + Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage)); + Current.Value = new RoomMatchPage(); + } + else + { + Items.ForEach(t => t.Enabled.Value = t is SettingsMatchPage); + Current.Value = new SettingsMatchPage(); + } + }, true); + } + + protected override TabItem CreateTabItem(MatchPage value) => new TabItem(value); + + private class TabItem : PageTabItem + { + private readonly IBindable enabled = new BindableBool(); + + public TabItem(MatchPage value) + : base(value) + { + enabled.BindTo(value.Enabled); + enabled.BindValueChanged(v => Colour = v ? Color4.White : Color4.Gray); + } + + protected override bool OnClick(ClickEvent e) + { + if (!enabled.Value) + return true; + return base.OnClick(e); + } + } + } +} diff --git a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs similarity index 99% rename from osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs rename to osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs index 4e0a9ff3a2..7fba56b2d3 100644 --- a/osu.Game/Screens/Multi/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs @@ -12,10 +12,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; +using osu.Game.Screens.Multi.Components; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Screens.Match { public class RoomSettingsOverlay : FocusedOverlayContainer { From ca544ef3fec321d67763ace251588af1fafee26a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 18:25:32 +0900 Subject: [PATCH 107/355] Adjust match creation process --- osu.Game/Screens/Multi/Screens/Match/Match.cs | 13 +-- .../Screens/Match/RoomSettingsOverlay.cs | 83 ++++++------------- 2 files changed, 26 insertions(+), 70 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index f444cb4073..40590a6982 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -32,8 +32,6 @@ namespace osu.Game.Screens.Multi.Screens.Match public override string ShortTitle => "room"; - private readonly Header header; - [Cached] private readonly Room room; @@ -55,6 +53,7 @@ namespace osu.Game.Screens.Multi.Screens.Match participantsBind.BindTo(room.Participants); maxParticipantsBind.BindTo(room.MaxParticipants); + Header header; RoomSettingsOverlay settings; Info info; @@ -81,8 +80,6 @@ namespace osu.Game.Screens.Multi.Screens.Match { RelativeSizeAxes = Axes.Both, Height = 0.9f, - Room = room, - ReadOnly = true }, }, }; @@ -98,14 +95,6 @@ namespace osu.Game.Screens.Multi.Screens.Match settings.Hide(); }; - settings.StateChanged += s => - { - if (s == Visibility.Hidden) - header.Tabs.Current.Value = new RoomMatchPage(); - }; - - settings.Applied = () => settings.Hide(); - info.Beatmap.BindTo(beatmapBind); info.Name.BindTo(nameBind); info.Status.BindTo(statusBind); diff --git a/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs index 7fba56b2d3..747c109e3f 100644 --- a/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -23,15 +23,12 @@ namespace osu.Game.Screens.Multi.Screens.Match private const float transition_duration = 350; private const float field_padding = 45; - /// - /// Invoked when room settings were applied. - /// - public Action Applied; - private readonly Bindable nameBind = new Bindable(); + private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); + private readonly Bindable createdBind = new Bindable(); private readonly Container content; @@ -43,6 +40,9 @@ namespace osu.Game.Screens.Multi.Screens.Match protected readonly TriangleButton ApplyButton; protected readonly OsuPasswordTextBox PasswordField; + [Resolved] + private Room room { get; set; } + public RoomSettingsOverlay() { Masking = true; @@ -151,69 +151,35 @@ namespace osu.Game.Screens.Multi.Screens.Match availabilityBind.ValueChanged += a => AvailabilityPicker.Current.Value = a; typeBind.ValueChanged += t => TypePicker.Current.Value = t; maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); - - Room = new Room(); } [BackgroundDependencyLoader] private void load(OsuColour colours) { typeLabel.Colour = colours.Yellow; + + nameBind.BindTo(room.Name); + beatmapBind.BindTo(room.Beatmap); + availabilityBind.BindTo(room.Availability); + typeBind.BindTo(room.Type); + maxParticipantsBind.BindTo(room.MaxParticipants); + createdBind.BindTo(room.Created); + + MaxParticipantsField.ReadOnly = true; + PasswordField.ReadOnly = true; + AvailabilityPicker.ReadOnly.Value = true; + TypePicker.ReadOnly.Value = true; + ApplyButton.Enabled.Value = false; } - private bool readOnly; - - public bool ReadOnly + protected override void Update() { - get => readOnly; - set - { - if (readOnly == value) - return; - readOnly = value; + base.Update(); - NameField.ReadOnly = value; - MaxParticipantsField.ReadOnly = value; - PasswordField.ReadOnly = value; - AvailabilityPicker.ReadOnly.Value = value; - TypePicker.ReadOnly.Value = value; - ApplyButton.Enabled.Value = !value; - } + ApplyButton.Enabled.Value = hasValidSettings; } - - private Room room; - - /// - /// The room which settings are being applied to. - /// - public virtual Room Room - { - get => room; - set - { - if (room == value) - return; - - if (room != null) - { - nameBind.UnbindFrom(room.Name); - availabilityBind.UnbindFrom(room.Availability); - typeBind.UnbindFrom(room.Type); - maxParticipantsBind.UnbindFrom(room.MaxParticipants); - } - - room = value; - - if (room != null) - { - nameBind.BindTo(room.Name); - availabilityBind.BindTo(room.Availability); - typeBind.BindTo(room.Type); - maxParticipantsBind.BindTo(room.MaxParticipants); - } - } - } + private bool hasValidSettings => NameField.Text.Length > 0 && beatmapBind.Value != null; protected override void PopIn() { @@ -245,7 +211,8 @@ namespace osu.Game.Screens.Multi.Screens.Match else maxParticipantsBind.Value = null; - Applied?.Invoke(); + // Todo: This should only be set after the room has been created server-side + createdBind.Value = true; } private class SettingsTextBox : OsuTextBox From 3f64cfc1c68144beb5065cc7096323771927cb4f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 18:35:08 +0900 Subject: [PATCH 108/355] Don't add rooms to lounge until they're actually created --- .../Screens/Multi/Screens/Lounge/Lounge.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 6fa254be05..19205065bc 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,6 +27,9 @@ namespace osu.Game.Screens.Multi.Screens.Lounge public override string Title => "Lounge"; + private Room roomBeingCreated; + private readonly IBindable roomCreated = new Bindable(); + protected override Drawable TransitionContent => content; public Lounge() @@ -74,6 +78,12 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; + + roomCreated.BindValueChanged(v => + { + if (v) + addRoom(roomBeingCreated); + }); } protected override void UpdateAfterChildren() @@ -147,8 +157,14 @@ namespace osu.Game.Screens.Multi.Screens.Lounge { if (Filter.Tabs.Current.Value == LoungeTab.Create) { + roomBeingCreated = new Room(); + + roomCreated.UnbindBindings(); + roomCreated.BindTo(roomBeingCreated.Created); + Filter.Tabs.Current.Value = LoungeTab.Public; - createRoom(new Room()); + + Push(new Match.Match(roomBeingCreated)); } search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; @@ -181,12 +197,6 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Push(new Match.Match(room.Room)); } - private void createRoom(Room room) - { - openRoom(addRoom(room)); - Filter.Tabs.Current.Value = LoungeTab.Public; - } - private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren { public IEnumerable FilterTerms => new string[] { }; From 3c44f9e4f132337e6f0b79b13c2cb85f8b699cd9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 18:50:52 +0900 Subject: [PATCH 109/355] Make select beatmap button into a triangle button --- .../Screens/Multi/Screens/Match/Header.cs | 78 +------------------ 1 file changed, 4 insertions(+), 74 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index 78a4a937a4..c06201a334 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -9,12 +9,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -75,6 +73,7 @@ namespace osu.Game.Screens.Multi.Screens.Match Child = beatmapButton = new BeatmapSelectButton { RelativeSizeAxes = Axes.Both, + Height = 1 }, }, Tabs = new MatchTabControl @@ -98,80 +97,11 @@ namespace osu.Game.Screens.Multi.Screens.Match tabStrip.Colour = colours.Yellow; } - private class BeatmapSelectButton : OsuClickableContainer + private class BeatmapSelectButton : TriangleButton { - private const float corner_radius = 5; - private const float bg_opacity = 0.5f; - private const float transition_duration = 100; - - private readonly Box bg; - private readonly Container border; - public BeatmapSelectButton() { - Masking = true; - CornerRadius = corner_radius; - - Children = new Drawable[] - { - bg = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = bg_opacity, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = @"Exo2.0-Bold", - Text = "Select Beatmap", - }, - border = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = corner_radius, - BorderThickness = 4, - Alpha = 0, - Child = new Box // needs a child to show the border - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - }, - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - border.BorderColour = colours.Yellow; - } - - protected override bool OnHover(HoverEvent e) - { - border.FadeIn(transition_duration); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - border.FadeOut(transition_duration); - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - bg.FadeTo(0.75f, 1000, Easing.Out); - return base.OnMouseDown(e); - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - bg.FadeTo(bg_opacity, transition_duration); - return base.OnMouseUp(e); + Text = "Select beatmap"; } } From cd41c456863aa1e74eafb70dd604c3735646d5df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 19:03:22 +0900 Subject: [PATCH 110/355] Disable select beatmap button after room is created --- .../Screens/Multi/Screens/Match/Header.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index c06201a334..7d3525370f 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -99,10 +100,22 @@ namespace osu.Game.Screens.Multi.Screens.Match private class BeatmapSelectButton : TriangleButton { + private readonly IBindable createdBind = new Bindable(); + + [Resolved] + private Room room { get; set; } + public BeatmapSelectButton() { Text = "Select beatmap"; } + + [BackgroundDependencyLoader] + private void load() + { + createdBind.BindTo(room.Created); + createdBind.BindValueChanged(v => Enabled.Value = !v, true); + } } private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite @@ -110,10 +123,4 @@ namespace osu.Game.Screens.Multi.Screens.Match protected override double FadeDuration => 0; } } - - public enum MatchHeaderPage - { - Settings, - Room, - } } From 1ac615b4905581b50c48e45c22f027a43ddb2a81 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Dec 2018 19:20:41 +0900 Subject: [PATCH 111/355] Renamespace --- osu.Game.Tests/Visual/TestCaseDrawableRoom.cs | 2 +- osu.Game.Tests/Visual/TestCaseLounge.cs | 40 +++++++++---------- osu.Game.Tests/Visual/TestCaseMatch.cs | 10 ++--- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 2 +- .../Visual/TestCaseMatchParticipants.cs | 2 +- osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 8 ++-- osu.Game.Tests/Visual/TestCaseMultiScreen.cs | 5 ++- .../Visual/TestCaseRoomInspector.cs | 2 +- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 3 +- osu.Game/Screens/Multi/Header.cs | 1 - .../Multi/{Screens => }/IMultiplayerScreen.cs | 2 +- .../{ => Lounge}/Components/DrawableRoom.cs | 3 +- .../Components}/FilterControl.cs | 2 +- .../Components/ParticipantInfo.cs | 2 +- .../{ => Lounge}/Components/RoomInspector.cs | 3 +- .../Lounge.cs => Lounge/LoungeScreen.cs} | 13 +++--- .../{ => Match}/Components/GameTypePicker.cs | 3 +- .../Match => Match/Components}/Header.cs | 2 +- .../Match => Match/Components}/Info.cs | 2 +- .../Match => Match/Components}/MatchPage.cs | 2 +- .../Components}/MatchTabControl.cs | 2 +- .../Components}/Participants.cs | 2 +- .../Components/RoomAvailabilityPicker.cs | 3 +- .../Components}/RoomSettingsOverlay.cs | 3 +- .../Match/Match.cs => Match/MatchScreen.cs} | 17 ++++---- osu.Game/Screens/Multi/Multiplayer.cs | 10 ++--- .../Multi/{Screens => }/MultiplayerScreen.cs | 2 +- osu.Game/Screens/Select/MatchSongSelect.cs | 2 +- 28 files changed, 77 insertions(+), 73 deletions(-) rename osu.Game/Screens/Multi/{Screens => }/IMultiplayerScreen.cs (85%) rename osu.Game/Screens/Multi/{ => Lounge}/Components/DrawableRoom.cs (99%) rename osu.Game/Screens/Multi/{Screens/Lounge => Lounge/Components}/FilterControl.cs (95%) rename osu.Game/Screens/Multi/{ => Lounge}/Components/ParticipantInfo.cs (99%) rename osu.Game/Screens/Multi/{ => Lounge}/Components/RoomInspector.cs (99%) rename osu.Game/Screens/Multi/{Screens/Lounge/Lounge.cs => Lounge/LoungeScreen.cs} (95%) rename osu.Game/Screens/Multi/{ => Match}/Components/GameTypePicker.cs (97%) rename osu.Game/Screens/Multi/{Screens/Match => Match/Components}/Header.cs (98%) rename osu.Game/Screens/Multi/{Screens/Match => Match/Components}/Info.cs (99%) rename osu.Game/Screens/Multi/{Screens/Match => Match/Components}/MatchPage.cs (93%) rename osu.Game/Screens/Multi/{Screens/Match => Match/Components}/MatchTabControl.cs (97%) rename osu.Game/Screens/Multi/{Screens/Match => Match/Components}/Participants.cs (98%) rename osu.Game/Screens/Multi/{ => Match}/Components/RoomAvailabilityPicker.cs (97%) rename osu.Game/Screens/Multi/{Screens/Match => Match/Components}/RoomSettingsOverlay.cs (99%) rename osu.Game/Screens/Multi/{Screens/Match/Match.cs => Match/MatchScreen.cs} (87%) rename osu.Game/Screens/Multi/{Screens => }/MultiplayerScreen.cs (97%) diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 8fd8880fd6..bcebf0a8d9 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index e0e6332ef0..ecf7c5194c 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.cs @@ -10,8 +10,8 @@ using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Multi.Components; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; using osuTK.Input; @@ -20,12 +20,12 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseLounge : ManualInputManagerTestCase { - private TestLounge lounge; + private TestLoungeScreen loungeScreen; [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - lounge = new TestLounge(); + loungeScreen = new TestLoungeScreen(); Room[] rooms = { @@ -159,47 +159,47 @@ namespace osu.Game.Tests.Visual }, }; - AddStep(@"show", () => Add(lounge)); - AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddStep(@"show", () => Add(loungeScreen)); + AddStep(@"set rooms", () => loungeScreen.Rooms = rooms); selectAssert(0); - AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); - AddAssert(@"no room selected", () => lounge.SelectedRoom == null); - AddStep(@"set rooms", () => lounge.Rooms = rooms); + AddStep(@"clear rooms", () => loungeScreen.Rooms = new Room[] {}); + AddAssert(@"no room selected", () => loungeScreen.SelectedRoom == null); + AddStep(@"set rooms", () => loungeScreen.Rooms = rooms); selectAssert(1); AddStep(@"open room 1", () => clickRoom(1)); - AddUntilStep(() => lounge.ChildScreen?.IsCurrentScreen == true, "wait until room current"); - AddStep(@"make lounge current", lounge.MakeCurrent); + AddUntilStep(() => loungeScreen.ChildScreen?.IsCurrentScreen == true, "wait until room current"); + AddStep(@"make lounge current", loungeScreen.MakeCurrent); filterAssert(@"THE FINAL", LoungeTab.Public, 1); filterAssert(string.Empty, LoungeTab.Public, 2); filterAssert(string.Empty, LoungeTab.Private, 1); filterAssert(string.Empty, LoungeTab.Public, 2); filterAssert(@"no matches", LoungeTab.Public, 0); - AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {}); - AddStep(@"set rooms", () => lounge.Rooms = rooms); - AddAssert(@"no matches after clear", () => !lounge.ChildRooms.Any()); + AddStep(@"clear rooms", () => loungeScreen.Rooms = new Room[] {}); + AddStep(@"set rooms", () => loungeScreen.Rooms = rooms); + AddAssert(@"no matches after clear", () => !loungeScreen.ChildRooms.Any()); filterAssert(string.Empty, LoungeTab.Public, 2); - AddStep(@"exit", lounge.Exit); + AddStep(@"exit", loungeScreen.Exit); } private void clickRoom(int n) { - InputManager.MoveMouseTo(lounge.ChildRooms.ElementAt(n)); + InputManager.MoveMouseTo(loungeScreen.ChildRooms.ElementAt(n)); InputManager.Click(MouseButton.Left); } private void selectAssert(int n) { AddStep($@"select room {n}", () => clickRoom(n)); - AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms.ElementAt(n).Room); + AddAssert($@"room {n} selected", () => loungeScreen.SelectedRoom == loungeScreen.ChildRooms.ElementAt(n).Room); } private void filterAssert(string filter, LoungeTab tab, int endCount) { - AddStep($@"filter '{filter}', {tab}", () => lounge.SetFilter(filter, tab)); - AddAssert(@"filtered correctly", () => lounge.ChildRooms.Count() == endCount); + AddStep($@"filter '{filter}', {tab}", () => loungeScreen.SetFilter(filter, tab)); + AddAssert(@"filtered correctly", () => loungeScreen.ChildRooms.Count() == endCount); } - private class TestLounge : Lounge + private class TestLoungeScreen : LoungeScreen { protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index 6099ed41bb..fd4806ac90 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -8,8 +8,8 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Components; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -96,9 +96,9 @@ namespace osu.Game.Tests.Visual }, }; - Match match = new Match(room); + MatchScreen matchScreen = new MatchScreen(room); - AddStep(@"show", () => Add(match)); + AddStep(@"show", () => Add(matchScreen)); AddStep(@"null beatmap", () => room.Beatmap.Value = null); AddStep(@"change name", () => room.Name.Value = @"Two Awesome Rooms"); AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); @@ -146,7 +146,7 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"exit", match.Exit); + AddStep(@"exit", matchScreen.Exit); } } } diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 6998ff4c39..37b3f6030d 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -6,7 +6,7 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match.Components; namespace osu.Game.Tests.Visual { diff --git a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs index 6024ec8ea6..67a56e525f 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index d27a447077..e416000f31 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -4,7 +4,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi.Lounge; namespace osu.Game.Tests.Visual { @@ -13,14 +13,14 @@ namespace osu.Game.Tests.Visual { public TestCaseMultiHeader() { - Lounge lounge; + LoungeScreen loungeScreen; Children = new Drawable[] { - lounge = new Lounge + loungeScreen = new LoungeScreen { Padding = new MarginPadding { Top = Header.HEIGHT }, }, - new Header(lounge), + new Header(loungeScreen), }; } } diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs index 9df057806e..c65ab4e3e3 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -5,7 +5,8 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Tests.Visual { @@ -15,7 +16,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(Multiplayer), - typeof(Lounge), + typeof(LoungeScreen), typeof(FilterControl) }; diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 06b9c4a6f9..57ed8419df 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index b0b287fdb3..19e27ddefe 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -8,8 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing.Input; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Components; -using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Screens.Multi.Match.Components; using osuTK.Input; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 612a3e6993..8e5a7381e9 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -10,7 +10,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Screens; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs b/osu.Game/Screens/Multi/IMultiplayerScreen.cs similarity index 85% rename from osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs rename to osu.Game/Screens/Multi/IMultiplayerScreen.cs index 0b6ebc3716..c1f43fa30d 100644 --- a/osu.Game/Screens/Multi/Screens/IMultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/IMultiplayerScreen.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 -namespace osu.Game.Screens.Multi.Screens +namespace osu.Game.Screens.Multi { public interface IMultiplayerScreen { diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs similarity index 99% rename from osu.Game/Screens/Multi/Components/DrawableRoom.cs rename to osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 9425457670..57ce9fc0b9 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -17,11 +17,12 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Lounge.Components { public class DrawableRoom : OsuClickableContainer, IStateful, IFilterable { diff --git a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs similarity index 95% rename from osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs rename to osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 301e235b79..fdc6c6f693 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -6,7 +6,7 @@ using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Lounge +namespace osu.Game.Screens.Multi.Lounge.Components { public class FilterControl : SearchableListFilterControl { diff --git a/osu.Game/Screens/Multi/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs similarity index 99% rename from osu.Game/Screens/Multi/Components/ParticipantInfo.cs rename to osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 47aff3f200..3bc20b58c5 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Lounge.Components { public class ParticipantInfo : Container { diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs similarity index 99% rename from osu.Game/Screens/Multi/Components/RoomInspector.cs rename to osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 07cf5541c5..496d8b52ca 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -17,11 +17,12 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osu.Game.Users; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Lounge.Components { public class RoomInspector : Container { diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs similarity index 95% rename from osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs rename to osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 19205065bc..3e81c7d652 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -11,12 +11,13 @@ using osu.Framework.Screens; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Multi.Lounge.Components; +using osu.Game.Screens.Multi.Match; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Lounge +namespace osu.Game.Screens.Multi.Lounge { - public class Lounge : MultiplayerScreen + public class LoungeScreen : MultiplayerScreen { private readonly Container content; private readonly SearchContainer search; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge protected override Drawable TransitionContent => content; - public Lounge() + public LoungeScreen() { Children = new Drawable[] { @@ -164,7 +165,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge Filter.Tabs.Current.Value = LoungeTab.Public; - Push(new Match.Match(roomBeingCreated)); + Push(new MatchScreen(roomBeingCreated)); } search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; @@ -194,7 +195,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge RoomsContainer.ForEach(c => c.State = c == room ? SelectionState.Selected : SelectionState.NotSelected); Inspector.Room = room.Room; - Push(new Match.Match(room.Room)); + Push(new MatchScreen(room.Room)); } private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren diff --git a/osu.Game/Screens/Multi/Components/GameTypePicker.cs b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs similarity index 97% rename from osu.Game/Screens/Multi/Components/GameTypePicker.cs rename to osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs index d9619ad35d..aec26a751e 100644 --- a/osu.Game/Screens/Multi/Components/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs @@ -9,9 +9,10 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osuTK; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Match.Components { public class GameTypePicker : DisableableTabControl { diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs similarity index 98% rename from osu.Game/Screens/Multi/Screens/Match/Header.cs rename to osu.Game/Screens/Multi/Match/Components/Header.cs index 7d3525370f..9c72403806 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -17,7 +17,7 @@ using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class Header : Container { diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs similarity index 99% rename from osu.Game/Screens/Multi/Screens/Match/Info.cs rename to osu.Game/Screens/Multi/Match/Components/Info.cs index d479765159..b3de5abf67 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -17,7 +17,7 @@ using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Components; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class Info : Container { diff --git a/osu.Game/Screens/Multi/Screens/Match/MatchPage.cs b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs similarity index 93% rename from osu.Game/Screens/Multi/Screens/Match/MatchPage.cs rename to osu.Game/Screens/Multi/Match/Components/MatchPage.cs index 710e41ec69..54ba345934 100644 --- a/osu.Game/Screens/Multi/Screens/Match/MatchPage.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs @@ -3,7 +3,7 @@ using osu.Framework.Configuration; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public abstract class MatchPage { diff --git a/osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs similarity index 97% rename from osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs rename to osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs index 5fd64179cd..51698fa50f 100644 --- a/osu.Game/Screens/Multi/Screens/Match/MatchTabControl.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class MatchTabControl : PageTabControl { diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs similarity index 98% rename from osu.Game/Screens/Multi/Screens/Match/Participants.cs rename to osu.Game/Screens/Multi/Match/Components/Participants.cs index 98ab758f81..92732dc045 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Multi.Components; using osu.Game.Users; using osuTK; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class Participants : CompositeDrawable { diff --git a/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs similarity index 97% rename from osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs rename to osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs index 287add5de1..4ddc9b30e9 100644 --- a/osu.Game/Screens/Multi/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs @@ -10,10 +10,11 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Components; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Components +namespace osu.Game.Screens.Multi.Match.Components { public class RoomAvailabilityPicker : DisableableTabControl { diff --git a/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs similarity index 99% rename from osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs rename to osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index 747c109e3f..56990403c2 100644 --- a/osu.Game/Screens/Multi/Screens/Match/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -12,11 +12,10 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Components; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match.Components { public class RoomSettingsOverlay : FocusedOverlayContainer { diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs similarity index 87% rename from osu.Game/Screens/Multi/Screens/Match/Match.cs rename to osu.Game/Screens/Multi/Match/MatchScreen.cs index 40590a6982..755b071f30 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -9,12 +9,13 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Select; using osu.Game.Users; -namespace osu.Game.Screens.Multi.Screens.Match +namespace osu.Game.Screens.Multi.Match { - public class Match : MultiplayerScreen + public class MatchScreen : MultiplayerScreen { private readonly Participants participants; @@ -41,7 +42,7 @@ namespace osu.Game.Screens.Multi.Screens.Match [Resolved] private APIAccess api { get; set; } - public Match(Room room) + public MatchScreen(Room room) { this.room = room; @@ -53,29 +54,29 @@ namespace osu.Game.Screens.Multi.Screens.Match participantsBind.BindTo(room.Participants); maxParticipantsBind.BindTo(room.MaxParticipants); - Header header; + Components.Header header; RoomSettingsOverlay settings; Info info; Children = new Drawable[] { - header = new Header + header = new Components.Header { Depth = -1, }, info = new Info { - Margin = new MarginPadding { Top = Header.HEIGHT }, + Margin = new MarginPadding { Top = Components.Header.HEIGHT }, }, participants = new Participants { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Header.HEIGHT + Info.HEIGHT }, + Padding = new MarginPadding { Top = Components.Header.HEIGHT + Info.HEIGHT }, }, new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Header.HEIGHT }, + Padding = new MarginPadding { Top = Components.Header.HEIGHT }, Child = settings = new RoomSettingsOverlay { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 7822fa68dc..d90e9ea33d 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Screens.Menu; -using osu.Game.Screens.Multi.Screens.Lounge; +using osu.Game.Screens.Multi.Lounge; namespace osu.Game.Screens.Multi { @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both, }; - Lounge lounge; + LoungeScreen loungeScreen; Children = new Drawable[] { new Container @@ -53,12 +53,12 @@ namespace osu.Game.Screens.Multi { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = lounge = new Lounge(), + Child = loungeScreen = new LoungeScreen(), }, - new Header(lounge), + new Header(loungeScreen), }; - lounge.Exited += s => Exit(); + loungeScreen.Exited += s => Exit(); } protected override void OnEntering(Screen last) diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/MultiplayerScreen.cs similarity index 97% rename from osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs rename to osu.Game/Screens/Multi/MultiplayerScreen.cs index 3184316a33..da9a2b3051 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerScreen.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Graphics.Containers; -namespace osu.Game.Screens.Multi.Screens +namespace osu.Game.Screens.Multi { public abstract class MultiplayerScreen : OsuScreen, IMultiplayerScreen { diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 28525215fb..94ac951159 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.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.Screens.Multi.Screens; +using osu.Game.Screens.Multi; namespace osu.Game.Screens.Select { From ea4dce845491503da0fd86a3c1b59a4a9c3d966e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 10 Dec 2018 21:08:14 +0900 Subject: [PATCH 112/355] Add a polling component model --- .../Visual/TestCasePollingComponent.cs | 98 ++++++++++++++++ osu.Game/Online/Chat/ChannelManager.cs | 93 +++++++-------- osu.Game/Online/PollingComponent.cs | 108 ++++++++++++++++++ osu.Game/OsuGame.cs | 2 + 4 files changed, 249 insertions(+), 52 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCasePollingComponent.cs create mode 100644 osu.Game/Online/PollingComponent.cs diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/TestCasePollingComponent.cs new file mode 100644 index 0000000000..928c92cb2b --- /dev/null +++ b/osu.Game.Tests/Visual/TestCasePollingComponent.cs @@ -0,0 +1,98 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using osu.Game.Online; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public class TestCasePollingComponent : OsuTestCase + { + private Container pollBox; + private TestPoller poller; + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + poller = new TestPoller(), + pollBox = new Container + { + Alpha = 0, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.4f), + Colour = Color4.LimeGreen, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Poll!", + } + } + } + }; + + int count = 0; + + poller.OnPoll += () => + { + pollBox.FadeOutFromOne(500); + count++; + }; + + AddStep("set poll to 1 second", () => poller.TimeBetweenPolls = TimePerAction); + + void checkCount(int checkValue) => AddAssert($"count is {checkValue}", () => count == checkValue); + + checkCount(1); + checkCount(2); + checkCount(3); + + AddStep("set poll to 5 second", () => poller.TimeBetweenPolls = TimePerAction * 5); + + checkCount(4); + checkCount(4); + checkCount(4); + checkCount(4); + + checkCount(5); + checkCount(5); + checkCount(5); + + AddStep("set poll to 5 second", () => poller.TimeBetweenPolls = TimePerAction); + + AddAssert("count is 6", () => count == 6); + + } + + protected override double TimePerAction => 500; + + public class TestPoller : PollingComponent + { + public event Action OnPoll; + + protected override Task Poll() + { + OnPoll?.Invoke(); + return base.Poll(); + } + } + } +} diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 863ad3042f..a63af0f7a3 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -4,11 +4,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.Graphics; using osu.Framework.Logging; -using osu.Framework.Threading; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Users; @@ -18,7 +17,7 @@ namespace osu.Game.Online.Chat /// /// Manages everything channel related /// - public class ChannelManager : Component, IOnlineComponent + public class ChannelManager : PollingComponent { /// /// The channels the player joins on startup @@ -49,11 +48,14 @@ namespace osu.Game.Online.Chat public IBindableCollection AvailableChannels => availableChannels; private IAPIProvider api; - private ScheduledDelegate fetchMessagesScheduleder; + + public readonly BindableBool HighPollRate = new BindableBool(); public ChannelManager() { CurrentChannel.ValueChanged += currentChannelChanged; + + HighPollRate.BindValueChanged(high => TimeBetweenPolls = high ? 1000 : 6000, true); } /// @@ -360,73 +362,60 @@ namespace osu.Game.Online.Chat } } - public void APIStateChanged(APIAccess api, APIState state) - { - switch (state) - { - case APIState.Online: - fetchUpdates(); - break; - default: - fetchMessagesScheduleder?.Cancel(); - fetchMessagesScheduleder = null; - break; - } - } - private long lastMessageId; - private const int update_poll_interval = 1000; private bool channelsInitialised; - private void fetchUpdates() + protected override Task Poll() { - fetchMessagesScheduleder?.Cancel(); - fetchMessagesScheduleder = Scheduler.AddDelayed(() => + if (!api.IsLoggedIn) + return base.Poll(); + + var fetchReq = new GetUpdatesRequest(lastMessageId); + + var tcs = new TaskCompletionSource(); + + fetchReq.Success += updates => { - var fetchReq = new GetUpdatesRequest(lastMessageId); - - fetchReq.Success += updates => + if (updates?.Presence != null) { - if (updates?.Presence != null) + foreach (var channel in updates.Presence) { - foreach (var channel in updates.Presence) - { - // we received this from the server so should mark the channel already joined. - JoinChannel(channel, true); - } - - //todo: handle left channels - - handleChannelMessages(updates.Messages); - - foreach (var group in updates.Messages.GroupBy(m => m.ChannelId)) - JoinedChannels.FirstOrDefault(c => c.Id == group.Key)?.AddNewMessages(group.ToArray()); - - lastMessageId = updates.Messages.LastOrDefault()?.Id ?? lastMessageId; + // we received this from the server so should mark the channel already joined. + JoinChannel(channel, true); } - if (!channelsInitialised) - { - channelsInitialised = true; - // we want this to run after the first presence so we can see if the user is in any channels already. - initializeChannels(); - } + //todo: handle left channels - fetchUpdates(); - }; + handleChannelMessages(updates.Messages); - fetchReq.Failure += delegate { fetchUpdates(); }; + foreach (var group in updates.Messages.GroupBy(m => m.ChannelId)) + JoinedChannels.FirstOrDefault(c => c.Id == group.Key)?.AddNewMessages(group.ToArray()); - api.Queue(fetchReq); - }, update_poll_interval); + lastMessageId = updates.Messages.LastOrDefault()?.Id ?? lastMessageId; + } + + if (!channelsInitialised) + { + channelsInitialised = true; + // we want this to run after the first presence so we can see if the user is in any channels already. + initializeChannels(); + } + + tcs.SetResult(true); + }; + + fetchReq.Failure += _ => tcs.SetResult(false); + + api.Queue(fetchReq); + + return tcs.Task; } [BackgroundDependencyLoader] private void load(IAPIProvider api) { this.api = api; - api.Register(this); } } diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs new file mode 100644 index 0000000000..d9dcfc40c2 --- /dev/null +++ b/osu.Game/Online/PollingComponent.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Threading.Tasks; +using osu.Framework.Graphics; +using osu.Framework.Threading; + +namespace osu.Game.Online +{ + /// + /// A component which requires a constant polling process. + /// + public abstract class PollingComponent : Component + { + private double? lastTimePolled; + + private ScheduledDelegate scheduledPoll; + + private bool pollingActive; + + private double timeBetweenPolls; + + /// + /// The time that should be waited between polls. + /// + public double TimeBetweenPolls + { + get => timeBetweenPolls; + set + { + timeBetweenPolls = value; + scheduledPoll?.Cancel(); + pollIfNecessary(); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + pollIfNecessary(); + } + + private bool pollIfNecessary() + { + // we must be loaded so we have access to clock. + if (!IsLoaded) return false; + + // there's already a poll process running. + if (pollingActive) return false; + + // don't try polling if the time between polls hasn't been set. + if (timeBetweenPolls == 0) return false; + + if (!lastTimePolled.HasValue) + { + doPoll(); + return true; + } + + if (Time.Current - lastTimePolled.Value > timeBetweenPolls) + { + doPoll(); + return true; + } + + // not ennough time has passed since the last poll. we do want to schedule a poll to happen, though. + scheduleNextPoll(); + return false; + } + + private void doPoll() + { + scheduledPoll = null; + pollingActive = true; + Poll().ContinueWith(_ => pollComplete()); + } + + /// + /// Perform the polling in this method. Call when done. + /// + protected virtual Task Poll() + { + return Task.CompletedTask; + } + + /// + /// Call when a poll operation has completed. + /// + private void pollComplete() + { + lastTimePolled = Time.Current; + pollingActive = false; + + if (scheduledPoll == null) + scheduleNextPoll(); + } + + private void scheduleNextPoll() + { + scheduledPoll?.Cancel(); + + double lastPollDuration = lastTimePolled.HasValue ? Time.Current - lastTimePolled.Value : 0; + + scheduledPoll = Scheduler.AddDelayed(doPoll, Math.Max(0, timeBetweenPolls - lastPollDuration)); + } + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 73ecbafb9e..31a00e68ac 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -418,6 +418,8 @@ namespace osu.Game dependencies.Cache(notifications); dependencies.Cache(dialogOverlay); + chatOverlay.StateChanged += state => channelManager.HighPollRate.Value = state == Visibility.Visible; + Add(externalLinkOpener = new ExternalLinkOpener()); var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications }; From bf3f5ab6854f0692e0a55f728b028d4a1f261f9c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Dec 2018 17:32:01 +0900 Subject: [PATCH 113/355] Change ready button to "Start" and make it enter player --- osu.Game/Screens/Multi/Header.cs | 7 ++- .../Screens/Multi/Match/Components/Info.cs | 63 ++----------------- .../Multi/Match/Components/ReadyButton.cs | 50 +++++++++++++++ osu.Game/Screens/Multi/Match/MatchScreen.cs | 17 +++++ osu.Game/Screens/Multi/Multiplayer.cs | 18 +++--- .../Screens/Multi/Play/TimeshiftPlayer.cs | 11 ++++ 6 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 osu.Game/Screens/Multi/Match/Components/ReadyButton.cs create mode 100644 osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 8e5a7381e9..570db11d50 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -85,7 +85,12 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => screenType.Text = ((IMultiplayerScreen)s).ShortTitle.ToLowerInvariant(); + breadcrumbs.Current.ValueChanged += s => + { + if (s is IMultiplayerScreen mpScreen) + screenType.Text = mpScreen.ShortTitle.ToLowerInvariant(); + }; + breadcrumbs.Current.TriggerChange(); } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index b3de5abf67..f13bf710e6 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -1,17 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Components; @@ -23,13 +22,12 @@ namespace osu.Game.Screens.Multi.Match.Components { public const float HEIGHT = 128; + public Action OnStart; + private readonly OsuSpriteText availabilityStatus; - private readonly ReadyButton readyButton; private OsuColour colours; - public Bindable Ready => readyButton.Ready; - public readonly Bindable Name = new Bindable(); public readonly Bindable Availability = new Bindable(); public readonly Bindable Status = new Bindable(); @@ -81,13 +79,14 @@ namespace osu.Game.Screens.Multi.Match.Components }, }, }, - readyButton = new ReadyButton + new ReadyButton { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, RelativeSizeAxes = Axes.Y, Size = new Vector2(200, 1), Padding = new MarginPadding { Vertical = 10 }, + Action = () => OnStart?.Invoke() }, }, }, @@ -125,57 +124,5 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityStatus.Text = $"{Availability.Value.GetDescription()}, {Status.Value.Message}"; } } - - private class ReadyButton : TriangleButton - { - public readonly Bindable Ready = new Bindable(); - - protected override SpriteText CreateText() => new OsuSpriteText - { - Depth = -1, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Font = @"Exo2.0-Light", - TextSize = 30, - }; - - [BackgroundDependencyLoader] - private void load() - { - BackgroundColour = OsuColour.FromHex(@"1187aa"); - Triangles.ColourLight = OsuColour.FromHex(@"277b9c"); - Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); - Triangles.TriangleScale = 1.5f; - - Container active; - Add(active = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.15f, - Blending = BlendingMode.Additive, - }, - }); - - Action = () => Ready.Value = !Ready.Value; - - Ready.BindValueChanged(value => - { - if (value) - { - Text = "Not Ready"; - active.FadeIn(200); - } - else - { - Text = "Ready"; - active.FadeOut(200); - } - }, true); - } - } } } diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs new file mode 100644 index 0000000000..f0ca013b62 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class ReadyButton : TriangleButton + { + [BackgroundDependencyLoader] + private void load() + { + BackgroundColour = OsuColour.FromHex(@"1187aa"); + + Triangles.ColourLight = OsuColour.FromHex(@"277b9c"); + Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); + Triangles.TriangleScale = 1.5f; + + Text = "Start"; + + Add(new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = 1f, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.15f, + Blending = BlendingMode.Additive, + }, + }); + } + + protected override SpriteText CreateText() => new OsuSpriteText + { + Depth = -1, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Font = @"Exo2.0-Light", + TextSize = 30, + }; + } +} diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 755b071f30..bbc4e2f4e0 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -10,6 +10,8 @@ using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Screens.Multi.Play; +using osu.Game.Screens.Play; using osu.Game.Screens.Select; using osu.Game.Users; @@ -36,6 +38,9 @@ namespace osu.Game.Screens.Multi.Match [Cached] private readonly Room room; + [Resolved] + private Multiplayer multiplayer { get; set; } + [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -67,6 +72,7 @@ namespace osu.Game.Screens.Multi.Match info = new Info { Margin = new MarginPadding { Top = Components.Header.HEIGHT }, + OnStart = onStart }, participants = new Participants { @@ -113,5 +119,16 @@ namespace osu.Game.Screens.Multi.Match beatmapBind.BindValueChanged(b => Beatmap.Value = beatmapManager.GetWorkingBeatmap(room.Beatmap.Value), true); Beatmap.BindValueChanged(b => beatmapBind.Value = b.BeatmapInfo); } + + private void onStart() + { + switch (typeBind.Value) + { + default: + case GameTypeTimeshift _: + multiplayer.Push(new PlayerLoader(new TimeshiftPlayer())); + break; + } + } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index d90e9ea33d..566621ffcd 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.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.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -13,21 +14,20 @@ using osu.Game.Screens.Multi.Lounge; namespace osu.Game.Screens.Multi { + [Cached] public class Multiplayer : OsuScreen { private readonly MultiplayerWaveContainer waves; - protected override Container Content => waves; - public Multiplayer() { - InternalChild = waves = new MultiplayerWaveContainer + Child = waves = new MultiplayerWaveContainer { RelativeSizeAxes = Axes.Both, }; LoungeScreen loungeScreen; - Children = new Drawable[] + waves.AddRange(new Drawable[] { new Container { @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi Child = loungeScreen = new LoungeScreen(), }, new Header(loungeScreen), - }; + }); loungeScreen.Exited += s => Exit(); } @@ -76,13 +76,17 @@ namespace osu.Game.Screens.Multi protected override void OnResuming(Screen last) { base.OnResuming(last); - waves.Show(); + + Content.FadeIn(250); + Content.ScaleTo(1, 250, Easing.OutSine); } protected override void OnSuspending(Screen next) { + Content.ScaleTo(1.1f, 250, Easing.InSine); + Content.FadeOut(250); + base.OnSuspending(next); - waves.Hide(); } protected override void LogoExiting(OsuLogo logo) diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs new file mode 100644 index 0000000000..114d90dc79 --- /dev/null +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Screens.Play; + +namespace osu.Game.Screens.Multi.Play +{ + public class TimeshiftPlayer : Player + { + } +} From 497f431366fa27bb6ddcd1df176d4cd4def55ead Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 11 Dec 2018 19:07:40 +0900 Subject: [PATCH 114/355] Implement RoomManager and RoomsContainer Reduces logic from LoungeScreen --- osu.Game.Tests/Visual/TestCaseLounge.cs | 18 +-- .../Visual/TestCaseRoomInspector.cs | 8 +- .../Multi/Lounge/Components/FilterControl.cs | 4 +- .../Multi/Lounge/Components/FilterCriteria.cs | 12 ++ .../Multi/Lounge/Components/RoomInspector.cs | 112 +++++++---------- .../Multi/Lounge/Components/RoomsContainer.cs | 104 +++++++++++++++ osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 118 +++--------------- .../Match/Components/RoomSettingsOverlay.cs | 8 +- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- osu.Game/Screens/Multi/RoomManager.cs | 32 +++++ 10 files changed, 229 insertions(+), 189 deletions(-) create mode 100644 osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs create mode 100644 osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs create mode 100644 osu.Game/Screens/Multi/RoomManager.cs diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs index ecf7c5194c..c1253e4f5c 100644 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ b/osu.Game.Tests/Visual/TestCaseLounge.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 System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -10,6 +8,7 @@ using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; +using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Lounge; using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; @@ -160,11 +159,8 @@ namespace osu.Game.Tests.Visual }; AddStep(@"show", () => Add(loungeScreen)); - AddStep(@"set rooms", () => loungeScreen.Rooms = rooms); selectAssert(0); - AddStep(@"clear rooms", () => loungeScreen.Rooms = new Room[] {}); AddAssert(@"no room selected", () => loungeScreen.SelectedRoom == null); - AddStep(@"set rooms", () => loungeScreen.Rooms = rooms); selectAssert(1); AddStep(@"open room 1", () => clickRoom(1)); AddUntilStep(() => loungeScreen.ChildScreen?.IsCurrentScreen == true, "wait until room current"); @@ -174,37 +170,33 @@ namespace osu.Game.Tests.Visual filterAssert(string.Empty, LoungeTab.Private, 1); filterAssert(string.Empty, LoungeTab.Public, 2); filterAssert(@"no matches", LoungeTab.Public, 0); - AddStep(@"clear rooms", () => loungeScreen.Rooms = new Room[] {}); - AddStep(@"set rooms", () => loungeScreen.Rooms = rooms); - AddAssert(@"no matches after clear", () => !loungeScreen.ChildRooms.Any()); filterAssert(string.Empty, LoungeTab.Public, 2); AddStep(@"exit", loungeScreen.Exit); } private void clickRoom(int n) { - InputManager.MoveMouseTo(loungeScreen.ChildRooms.ElementAt(n)); InputManager.Click(MouseButton.Left); } private void selectAssert(int n) { AddStep($@"select room {n}", () => clickRoom(n)); - AddAssert($@"room {n} selected", () => loungeScreen.SelectedRoom == loungeScreen.ChildRooms.ElementAt(n).Room); } private void filterAssert(string filter, LoungeTab tab, int endCount) { AddStep($@"filter '{filter}', {tab}", () => loungeScreen.SetFilter(filter, tab)); - AddAssert(@"filtered correctly", () => loungeScreen.ChildRooms.Count() == endCount); } private class TestLoungeScreen : LoungeScreen { protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); - public IEnumerable ChildRooms => RoomsContainer.Children.Where(r => r.MatchingFilter); - public Room SelectedRoom => Inspector.Room; + [Resolved] + private RoomManager manager { get; set; } + + public Room SelectedRoom => manager.Current.Value; public void SetFilter(string filter, LoungeTab tab) { diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 57ed8419df..9f6eea68e7 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -66,8 +66,7 @@ namespace osu.Game.Tests.Visual } }; - RoomInspector inspector; - Add(inspector = new RoomInspector + Add(new RoomInspector { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -75,9 +74,6 @@ namespace osu.Game.Tests.Visual Width = 0.5f, }); - AddStep(@"set room", () => inspector.Room = room); - AddStep(@"null room", () => inspector.Room = null); - AddStep(@"set room", () => inspector.Room = room); AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above"); AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } }); AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); @@ -133,8 +129,6 @@ namespace osu.Game.Tests.Visual } } }; - - inspector.Room = newRoom; }); } diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index fdc6c6f693..ddab9c197e 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -18,7 +18,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components DisplayStyleControl.Hide(); } - public RoomAvailability Availability + public FilterCriteria CreateCriteria() => new FilterCriteria { Availability = availability }; + + private RoomAvailability availability { get { diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs new file mode 100644 index 0000000000..ec62ef1bdf --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public class FilterCriteria + { + public RoomAvailability Availability; + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 496d8b52ca..e8de201b8f 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -28,6 +28,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components { private const float transition_duration = 100; + public readonly Bindable Room = new Bindable(); + private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); private readonly Bindable beatmapBind = new Bindable(); @@ -52,43 +54,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components [Resolved] private BeatmapManager beatmaps { get; set; } - private Room room; - public Room Room - { - get => room; - set - { - if (value == room) - return; - - if (room != null) - { - nameBind.UnbindFrom(room.Name); - hostBind.UnbindFrom(room.Host); - statusBind.UnbindFrom(room.Status); - typeBind.UnbindFrom(room.Type); - beatmapBind.UnbindFrom(room.Beatmap); - maxParticipantsBind.UnbindFrom(room.MaxParticipants); - participantsBind.UnbindFrom(room.Participants); - } - - room = value; - - if (room != null) - { - nameBind.BindTo(room.Name); - hostBind.BindTo(room.Host); - statusBind.BindTo(room.Status); - typeBind.BindTo(room.Type); - beatmapBind.BindTo(room.Beatmap); - maxParticipantsBind.BindTo(room.MaxParticipants); - participantsBind.BindTo(room.Participants); - } - - updateState(); - } - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -226,7 +191,52 @@ namespace osu.Game.Screens.Multi.Lounge.Components beatmapTypeInfo.Type.BindTo(typeBind); beatmapTypeInfo.Beatmap.BindTo(beatmapBind); - updateState(); + Room.BindValueChanged(updateRoom, true); + } + + private Room lastRoom; + + private void updateRoom(Room newRoom) + { + if (lastRoom != null) + { + nameBind.UnbindFrom(lastRoom.Name); + hostBind.UnbindFrom(lastRoom.Host); + statusBind.UnbindFrom(lastRoom.Status); + typeBind.UnbindFrom(lastRoom.Type); + beatmapBind.UnbindFrom(lastRoom.Beatmap); + maxParticipantsBind.UnbindFrom(lastRoom.MaxParticipants); + participantsBind.UnbindFrom(lastRoom.Participants); + } + + if (newRoom != null) + { + nameBind.BindTo(newRoom.Name); + hostBind.BindTo(newRoom.Host); + statusBind.BindTo(newRoom.Status); + typeBind.BindTo(newRoom.Type); + beatmapBind.BindTo(newRoom.Beatmap); + maxParticipantsBind.BindTo(newRoom.MaxParticipants); + participantsBind.BindTo(newRoom.Participants); + + participantsFlow.FadeIn(transition_duration); + participantCount.FadeIn(transition_duration); + beatmapTypeInfo.FadeIn(transition_duration); + name.FadeIn(transition_duration); + participantInfo.FadeIn(transition_duration); + } + else + { + participantsFlow.FadeOut(transition_duration); + participantCount.FadeOut(transition_duration); + beatmapTypeInfo.FadeOut(transition_duration); + name.FadeOut(transition_duration); + participantInfo.FadeOut(transition_duration); + + displayStatus(new RoomStatusNoneSelected()); + } + + lastRoom = newRoom; } protected override void UpdateAfterChildren() @@ -245,32 +255,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components status.FadeColour(c, transition_duration); } - private void updateState() - { - if (Room == null) - { - beatmap.Value = null; - participantsFlow.FadeOut(transition_duration); - participantCount.FadeOut(transition_duration); - beatmapTypeInfo.FadeOut(transition_duration); - name.FadeOut(transition_duration); - participantInfo.FadeOut(transition_duration); - - displayStatus(new RoomStatusNoneSelected()); - } - else - { - participantsFlow.FadeIn(transition_duration); - participantCount.FadeIn(transition_duration); - beatmapTypeInfo.FadeIn(transition_duration); - name.FadeIn(transition_duration); - participantInfo.FadeIn(transition_duration); - - statusBind.TriggerChange(); - beatmapBind.TriggerChange(); - } - } - private class UserTile : Container, IHasTooltip { private readonly User user; diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs new file mode 100644 index 0000000000..072a892954 --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -0,0 +1,104 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osuTK; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public class RoomsContainer : CompositeDrawable, IHasFilterableChildren + { + public Action OpenRequested; + + private readonly IBindableCollection rooms = new BindableCollection(); + private readonly Bindable currentRoom = new Bindable(); + + private readonly FillFlowContainer roomFlow; + + [Resolved] + private RoomManager manager { get; set; } + + public RoomsContainer() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChild = roomFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2), + }; + } + + [BackgroundDependencyLoader] + private void load() + { + currentRoom.BindTo(manager.Current); + rooms.BindTo(manager.Rooms); + + rooms.ItemsAdded += addRooms; + rooms.ItemsRemoved += removeRooms; + + addRooms(rooms); + + currentRoom.BindValueChanged(selectRoom, true); + } + + private FilterCriteria currentFilter; + + public void Filter(FilterCriteria criteria) + { + roomFlow.Children.ForEach(r => r.MatchingFilter = criteria == null || r.Room.Availability == criteria.Availability); + currentFilter = criteria; + } + + private void addRooms(IEnumerable rooms) + { + foreach (var r in rooms) + roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); + + Filter(currentFilter); + } + + private void removeRooms(IEnumerable rooms) + { + foreach (var r in rooms) + { + var toRemove = roomFlow.Single(d => d.Room == r); + toRemove.Action = null; + + roomFlow.Remove(toRemove); + } + } + + private void selectRoom(Room room) + { + var drawable = roomFlow.FirstOrDefault(r => r.Room == room); + + if (drawable != null && drawable.State == SelectionState.Selected) + OpenRequested?.Invoke(room); + else + { + currentRoom.Value = room; + roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected); + } + } + + public IEnumerable FilterTerms => Enumerable.Empty(); + + public IEnumerable FilterableChildren => InternalChildren.OfType(); + + public bool MatchingFilter { set { } } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 3e81c7d652..1b49e0c1b3 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -1,40 +1,37 @@ // 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.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Screens; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Match; -using osuTK; namespace osu.Game.Screens.Multi.Lounge { public class LoungeScreen : MultiplayerScreen { + protected readonly FilterControl Filter; + private readonly Container content; private readonly SearchContainer search; + private readonly RoomsContainer rooms; - protected readonly FilterControl Filter; - protected readonly FillFlowContainer RoomsContainer; - protected readonly RoomInspector Inspector; + [Cached] + private readonly RoomManager manager; public override string Title => "Lounge"; - private Room roomBeingCreated; - private readonly IBindable roomCreated = new Bindable(); - protected override Drawable TransitionContent => content; public LoungeScreen() { + RoomInspector inspector; + Children = new Drawable[] { Filter = new FilterControl { Depth = -1 }, @@ -56,16 +53,10 @@ namespace osu.Game.Screens.Multi.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = RoomsContainer = new RoomsFilterContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(10 - DrawableRoom.SELECTION_BORDER_WIDTH * 2), - }, + Child = rooms = new RoomsContainer { OpenRequested = openRoom } }, }, - Inspector = new RoomInspector + inspector = new RoomInspector { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -73,18 +64,15 @@ namespace osu.Game.Screens.Multi.Lounge Width = 0.45f, }, }, - } + }, + manager = new RoomManager() }; + inspector.Room.BindTo(manager.Current); + Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); Filter.Search.Exit += Exit; - - roomCreated.BindValueChanged(v => - { - if (v) - addRoom(roomBeingCreated); - }); } protected override void UpdateAfterChildren() @@ -99,31 +87,6 @@ namespace osu.Game.Screens.Multi.Lounge }; } - public IEnumerable Rooms - { - set - { - RoomsContainer.ForEach(r => r.Action = null); - RoomsContainer.Clear(); - - foreach (var room in value) - addRoom(room); - } - } - - private DrawableRoom addRoom(Room room) - { - var drawableRoom = new DrawableRoom(room); - - drawableRoom.Action = () => selectionRequested(drawableRoom); - - RoomsContainer.Add(drawableRoom); - - filterRooms(); - - return drawableRoom; - } - protected override void OnFocus(FocusEvent e) { GetContainingInputManager().ChangeFocus(Filter.Search); @@ -158,65 +121,22 @@ namespace osu.Game.Screens.Multi.Lounge { if (Filter.Tabs.Current.Value == LoungeTab.Create) { - roomBeingCreated = new Room(); - - roomCreated.UnbindBindings(); - roomCreated.BindTo(roomBeingCreated.Created); - Filter.Tabs.Current.Value = LoungeTab.Public; - - Push(new MatchScreen(roomBeingCreated)); + Push(new MatchScreen(new Room())); } search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; - foreach (DrawableRoom r in RoomsContainer.Children) - { - r.MatchingFilter = r.MatchingFilter && r.Room.Availability.Value == Filter.Availability; - } + rooms.Filter(Filter.CreateCriteria()); } - private void selectionRequested(DrawableRoom room) - { - if (room.State == SelectionState.Selected) - openRoom(room); - else - { - RoomsContainer.ForEach(c => c.State = c == room ? SelectionState.Selected : SelectionState.NotSelected); - Inspector.Room = room.Room; - } - } - - private void openRoom(DrawableRoom room) + private void openRoom(Room room) { + // Handles the case where a room is clicked 3 times in quick succession if (!IsCurrentScreen) return; - RoomsContainer.ForEach(c => c.State = c == room ? SelectionState.Selected : SelectionState.NotSelected); - Inspector.Room = room.Room; - - Push(new MatchScreen(room.Room)); - } - - private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren - { - public IEnumerable FilterTerms => new string[] { }; - public IEnumerable FilterableChildren => Children; - - public bool MatchingFilter - { - set - { - if (value) - InvalidateLayout(); - } - } - - public RoomsFilterContainer() - { - LayoutDuration = 200; - LayoutEasing = Easing.OutQuint; - } + Push(new MatchScreen(room)); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index 56990403c2..e4eb2046b2 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -27,7 +27,6 @@ namespace osu.Game.Screens.Multi.Match.Components private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); - private readonly Bindable createdBind = new Bindable(); private readonly Container content; @@ -39,6 +38,9 @@ namespace osu.Game.Screens.Multi.Match.Components protected readonly TriangleButton ApplyButton; protected readonly OsuPasswordTextBox PasswordField; + [Resolved] + private RoomManager manager { get; set; } + [Resolved] private Room room { get; set; } @@ -162,7 +164,6 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityBind.BindTo(room.Availability); typeBind.BindTo(room.Type); maxParticipantsBind.BindTo(room.MaxParticipants); - createdBind.BindTo(room.Created); MaxParticipantsField.ReadOnly = true; PasswordField.ReadOnly = true; @@ -210,8 +211,7 @@ namespace osu.Game.Screens.Multi.Match.Components else maxParticipantsBind.Value = null; - // Todo: This should only be set after the room has been created server-side - createdBind.Value = true; + manager.CreateRoom(room); } private class SettingsTextBox : OsuTextBox diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index d90e9ea33d..aba83753cb 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Multi Padding = new MarginPadding { Top = Header.HEIGHT }, Child = loungeScreen = new LoungeScreen(), }, - new Header(loungeScreen), + new Header(loungeScreen) }; loungeScreen.Exited += s => Exit(); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs new file mode 100644 index 0000000000..9e233f278b --- /dev/null +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi +{ + public class RoomManager : Component + { + public IBindableCollection Rooms => rooms; + private readonly BindableCollection rooms = new BindableCollection(); + + public readonly Bindable Current = new Bindable(); + + [Resolved] + private APIAccess api { get; set; } + + public void CreateRoom(Room room) + { + room.Host.Value = api.LocalUser; + + // Todo: Perform API request + + room.Created.Value = true; + rooms.Add(room); + } + } +} From 7dc1f5b771fa1f5c9bd88ab53a3162da7278029e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Dec 2018 20:12:30 +0900 Subject: [PATCH 115/355] Add more tests --- .../Visual/TestCasePollingComponent.cs | 110 +++++++++++++----- 1 file changed, 78 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/TestCasePollingComponent.cs index 928c92cb2b..bf129bfd53 100644 --- a/osu.Game.Tests/Visual/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/TestCasePollingComponent.cs @@ -3,10 +3,11 @@ using System; using System.Threading.Tasks; -using osu.Framework.Allocation; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; using osu.Game.Graphics.Sprites; using osu.Game.Online; using osuTK; @@ -19,12 +20,16 @@ namespace osu.Game.Tests.Visual private Container pollBox; private TestPoller poller; - [BackgroundDependencyLoader] - private void load() + private const float safety_adjust = 1f; + private int count; + + [SetUp] + public void SetUp() => Schedule(() => { + count = 0; + Children = new Drawable[] { - poller = new TestPoller(), pollBox = new Container { Alpha = 0, @@ -48,41 +53,77 @@ namespace osu.Game.Tests.Visual } } }; + }); - int count = 0; + //[Test] + public void TestInstantPolling() + { + createPoller(true); + AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust); + checkCount(1); + checkCount(2); + checkCount(3); + + AddStep("set poll interval to 5", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust * 5); + checkCount(4); + checkCount(4); + checkCount(4); + + skip(); + + checkCount(5); + checkCount(5); + + AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust); + checkCount(6); + checkCount(7); + } + + [Test] + public void TestSlowPolling() + { + createPoller(false); + + AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust * 5); + checkCount(0); + skip(); + checkCount(0); + skip(); + skip(); + skip(); + skip(); + checkCount(0); + skip(); + skip(); + checkCount(0); + } + + private void skip() => AddStep("skip", () => + { + // could be 4 or 5 at this point due to timing discrepancies (safety_adjust @ 0.2 * 5 ~= 1) + // easiest to just ignore the value at this point and move on. + }); + + private void checkCount(int checkValue) + { + Logger.Log($"value is {count}"); + AddAssert($"count is {checkValue}", () => count == checkValue); + } + + private void createPoller(bool instant) => AddStep("create poller", () => + { + poller?.Expire(); + + Add(poller = instant ? new TestPoller() : new TestSlowPoller()); poller.OnPoll += () => { pollBox.FadeOutFromOne(500); count++; }; + }); - AddStep("set poll to 1 second", () => poller.TimeBetweenPolls = TimePerAction); - - void checkCount(int checkValue) => AddAssert($"count is {checkValue}", () => count == checkValue); - - checkCount(1); - checkCount(2); - checkCount(3); - - AddStep("set poll to 5 second", () => poller.TimeBetweenPolls = TimePerAction * 5); - - checkCount(4); - checkCount(4); - checkCount(4); - checkCount(4); - - checkCount(5); - checkCount(5); - checkCount(5); - - AddStep("set poll to 5 second", () => poller.TimeBetweenPolls = TimePerAction); - - AddAssert("count is 6", () => count == 6); - - } - - protected override double TimePerAction => 500; + protected override double TimePerAction => 5000; public class TestPoller : PollingComponent { @@ -90,9 +131,14 @@ namespace osu.Game.Tests.Visual protected override Task Poll() { - OnPoll?.Invoke(); + Schedule(() => OnPoll?.Invoke()); return base.Poll(); } } + + public class TestSlowPoller : TestPoller + { + protected override Task Poll() => Task.Delay((int)(TimeBetweenPolls / 2f / Clock.Rate)).ContinueWith(_ => base.Poll()); + } } } From 49dd6ae9b0b8993977b66e7c3f4eb992e331f20d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 13:21:44 +0900 Subject: [PATCH 116/355] Move a lot more of PlaySongSelect into SongSelect --- osu.Game/Screens/Select/PlaySongSelect.cs | 103 ++-------------------- osu.Game/Screens/Select/SongSelect.cs | 95 ++++++++++++++++---- 2 files changed, 85 insertions(+), 113 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 8d37da0377..cbe22d968a 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,99 +1,28 @@ // 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 osuTK.Input; using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; -using osu.Framework.Graphics; using osu.Framework.Screens; -using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Overlays; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; -using osu.Game.Screens.Ranking; -using osu.Game.Skinning; +using osuTK.Input; namespace osu.Game.Screens.Select { public class PlaySongSelect : SongSelect { - private OsuScreen player; - protected readonly BeatmapDetailArea BeatmapDetails; private bool removeAutoModOnResume; + private OsuScreen player; - public PlaySongSelect() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - LeftContent.Add(BeatmapDetails = new BeatmapDetailArea - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 10, Right = 5 }, - }); - - BeatmapDetails.Leaderboard.ScoreSelected += s => Push(new Results(s)); - } - - private SampleChannel sampleConfirm; - - [Cached] - [Cached(Type = typeof(IBindable>))] - private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); - - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay, Bindable> selectedMods) - { - if (selectedMods != null) this.selectedMods.BindTo(selectedMods); - - sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); - - BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1); - BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, null, Key.Number2); BeatmapOptions.AddButton(@"Edit", @"beatmap", FontAwesome.fa_pencil, colours.Yellow, () => { ValidForResume = false; Edit(); }, Key.Number3); - - if (dialogOverlay != null) - { - Schedule(() => - { - // if we have no beatmaps but osu-stable is found, let's prompt the user to import. - if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) - dialogOverlay.Push(new ImportFromStablePopup(() => - { - beatmaps.ImportFromStableAsync(); - skins.ImportFromStableAsync(); - })); - }); - } - } - - protected override void ExitFromBack() - { - if (modSelect.State == Visibility.Visible) - { - modSelect.Hide(); - return; - } - - base.ExitFromBack(); - } - - protected override void UpdateBeatmap(WorkingBeatmap beatmap) - { - beatmap.Mods.BindTo(selectedMods); - - base.UpdateBeatmap(beatmap); - - BeatmapDetails.Beatmap = beatmap; - - if (beatmap.Track != null) - beatmap.Track.Looping = true; } protected override void OnResuming(Screen last) @@ -107,27 +36,9 @@ namespace osu.Game.Screens.Select removeAutoModOnResume = false; } - BeatmapDetails.Leaderboard.RefreshScores(); - - Beatmap.Value.Track.Looping = true; - base.OnResuming(last); } - protected override bool OnExiting(Screen next) - { - if (base.OnExiting(next)) - return true; - - if (Beatmap.Value.Track != null) - Beatmap.Value.Track.Looping = false; - - selectedMods.UnbindAll(); - Beatmap.Value.Mods.Value = new Mod[] { }; - - return false; - } - protected override bool OnStart() { if (player != null) return false; @@ -138,10 +49,10 @@ namespace osu.Game.Screens.Select var auto = Ruleset.Value.CreateInstance().GetAutoplayMod(); var autoType = auto.GetType(); - var mods = selectedMods.Value; + var mods = SelectedMods.Value; if (mods.All(m => m.GetType() != autoType)) { - selectedMods.Value = mods.Append(auto); + SelectedMods.Value = mods.Append(auto); removeAutoModOnResume = true; } } @@ -149,7 +60,7 @@ namespace osu.Game.Screens.Select Beatmap.Value.Track.Looping = false; Beatmap.Disabled = true; - sampleConfirm?.Play(); + SampleConfirm?.Play(); LoadComponentAsync(player = new PlayerLoader(new Player()), l => { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index c7e999f7c7..71b63c8e5b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.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 System.Linq; using osuTK; using osuTK.Input; @@ -27,7 +28,9 @@ using osu.Game.Rulesets.Mods; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Edit; using osu.Game.Screens.Menu; +using osu.Game.Screens.Ranking; using osu.Game.Screens.Select.Options; +using osu.Game.Skinning; namespace osu.Game.Screens.Select { @@ -61,8 +64,6 @@ namespace osu.Game.Screens.Select protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); - protected Container LeftContent; - protected readonly BeatmapCarousel Carousel; private readonly BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; @@ -70,22 +71,17 @@ namespace osu.Game.Screens.Select protected readonly ModSelectOverlay ModSelect; + protected SampleChannel SampleConfirm; private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeBeatmap; + protected readonly BeatmapDetailArea BeatmapDetails; + protected new readonly Bindable Ruleset = new Bindable(); - private DependencyContainer dependencies; - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(this); - dependencies.CacheAs(Ruleset); - dependencies.CacheAs>(Ruleset); - - return dependencies; - } + [Cached] + [Cached(Type = typeof(IBindable>))] + protected readonly Bindable> SelectedMods = new Bindable>(new Mod[] { }); protected SongSelect() { @@ -108,7 +104,7 @@ namespace osu.Game.Screens.Select } } }, - LeftContent = new Container + new Container { Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, @@ -120,6 +116,11 @@ namespace osu.Game.Screens.Select Top = wedged_container_size.Y + left_area_padding, Left = left_area_padding, Right = left_area_padding * 2, + }, + Child = BeatmapDetails = new BeatmapDetailArea + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 10, Right = 5 }, } }, new Container @@ -208,13 +209,16 @@ namespace osu.Game.Screens.Select } }); } + + BeatmapDetails.Leaderboard.ScoreSelected += s => Push(new Results(s)); } - protected virtual void ExitFromBack() => Exit(); - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, Bindable> selectedMods) { + if (selectedMods != null) + SelectedMods.BindTo(selectedMods); + if (Footer != null) { Footer.AddButton(@"mods", colours.Yellow, ModSelect, Key.F1); @@ -222,6 +226,8 @@ namespace osu.Game.Screens.Select Footer.AddButton(@"options", colours.Blue, BeatmapOptions, Key.F3); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.fa_trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); + BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1); + BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, null, Key.Number2); } if (this.beatmaps == null) @@ -236,8 +242,46 @@ namespace osu.Game.Screens.Select sampleChangeDifficulty = audio.Sample.Get(@"SongSelect/select-difficulty"); sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); + SampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); Carousel.LoadBeatmapSetsFromManager(this.beatmaps); + + if (dialogOverlay != null) + { + Schedule(() => + { + // if we have no beatmaps but osu-stable is found, let's prompt the user to import. + if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) + dialogOverlay.Push(new ImportFromStablePopup(() => + { + beatmaps.ImportFromStableAsync(); + skins.ImportFromStableAsync(); + })); + }); + } + } + + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(this); + dependencies.CacheAs(Ruleset); + dependencies.CacheAs>(Ruleset); + + return dependencies; + } + + protected virtual void ExitFromBack() + { + if (ModSelect.State == Visibility.Visible) + { + ModSelect.Hide(); + return; + } + + Exit(); } public void Edit(BeatmapInfo beatmap = null) @@ -434,6 +478,10 @@ namespace osu.Game.Screens.Select protected override void OnResuming(Screen last) { + BeatmapDetails.Leaderboard.RefreshScores(); + + Beatmap.Value.Track.Looping = true; + if (Beatmap != null && !Beatmap.Value.BeatmapSetInfo.DeletePending) { UpdateBeatmap(Beatmap.Value); @@ -477,6 +525,12 @@ namespace osu.Game.Screens.Select FilterControl.Deactivate(); + if (Beatmap.Value.Track != null) + Beatmap.Value.Track.Looping = false; + + SelectedMods.UnbindAll(); + Beatmap.Value.Mods.Value = new Mod[] { }; + return base.OnExiting(next); } @@ -502,6 +556,8 @@ namespace osu.Game.Screens.Select /// The working beatmap. protected virtual void UpdateBeatmap(WorkingBeatmap beatmap) { + beatmap.Mods.BindTo(SelectedMods); + Logger.Log($"working beatmap updated to {beatmap}"); if (Background is BackgroundScreenBeatmap backgroundModeBeatmap) @@ -512,6 +568,11 @@ namespace osu.Game.Screens.Select } beatmapInfoWedge.Beatmap = beatmap; + + BeatmapDetails.Beatmap = beatmap; + + if (beatmap.Track != null) + beatmap.Track.Looping = true; } private void ensurePlayingSelected(bool preview = false) From 170955110ff9acb96594d8848fad96528070a4b9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 14:38:03 +0900 Subject: [PATCH 117/355] Add mods to the match info --- .../Screens/Multi/Match/Components/Info.cs | 24 ++++++++++++++++--- osu.Game/Screens/Multi/Match/MatchScreen.cs | 6 +++++ osu.Game/Screens/Play/HUD/ModDisplay.cs | 7 ++++-- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index b3de5abf67..fe6343e4db 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.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.Configuration; using osu.Framework.Extensions; @@ -14,14 +15,16 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Play.HUD; using osuTK; namespace osu.Game.Screens.Multi.Match.Components { public class Info : Container { - public const float HEIGHT = 128; + public const float HEIGHT = 156; private readonly OsuSpriteText availabilityStatus; private readonly ReadyButton readyButton; @@ -35,6 +38,7 @@ namespace osu.Game.Screens.Multi.Match.Components public readonly Bindable Status = new Bindable(); public readonly Bindable Beatmap = new Bindable(); public readonly Bindable Type = new Bindable(); + public readonly Bindable> Mods = new Bindable>(); public Info() { @@ -43,6 +47,7 @@ namespace osu.Game.Screens.Multi.Match.Components BeatmapTypeInfo beatmapTypeInfo; OsuSpriteText name; + ModDisplay modDisplay; Children = new Drawable[] { @@ -74,11 +79,23 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityStatus = new OsuSpriteText { TextSize = 14 }, }, }, - beatmapTypeInfo = new BeatmapTypeInfo + new FillFlowContainer { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - }, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + beatmapTypeInfo = new BeatmapTypeInfo(), + modDisplay = new ModDisplay + { + Scale = new Vector2(0.75f), + DisplayUnrankedText = false + }, + } + } + }, }, readyButton = new ReadyButton @@ -95,6 +112,7 @@ namespace osu.Game.Screens.Multi.Match.Components beatmapTypeInfo.Beatmap.BindTo(Beatmap); beatmapTypeInfo.Type.BindTo(Type); + modDisplay.Current.BindTo(Mods); Availability.BindValueChanged(_ => updateAvailabilityStatus()); Status.BindValueChanged(_ => updateAvailabilityStatus()); diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 755b071f30..ecc5c91be3 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -2,6 +2,7 @@ // 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.Configuration; using osu.Framework.Graphics; @@ -9,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Select; using osu.Game.Users; @@ -33,6 +35,9 @@ namespace osu.Game.Screens.Multi.Match public override string ShortTitle => "room"; + [Cached] + private readonly Bindable> mods = new Bindable>(Enumerable.Empty()); + [Cached] private readonly Room room; @@ -101,6 +106,7 @@ namespace osu.Game.Screens.Multi.Match info.Status.BindTo(statusBind); info.Availability.BindTo(availabilityBind); info.Type.BindTo(typeBind); + info.Mods.BindTo(mods); participants.Users.BindTo(participantsBind); participants.MaxParticipants.BindTo(maxParticipantsBind); diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 9509c7acae..7536501c90 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -20,6 +20,8 @@ namespace osu.Game.Screens.Play.HUD { private const int fade_duration = 1000; + public bool DisplayUnrankedText = true; + private readonly Bindable> mods = new Bindable>(); public Bindable> Current => mods; @@ -29,6 +31,8 @@ namespace osu.Game.Screens.Play.HUD public ModDisplay() { + AutoSizeAxes = Axes.Both; + Children = new Drawable[] { iconsContainer = new ReverseChildIDFillFlowContainer @@ -41,7 +45,6 @@ namespace osu.Game.Screens.Play.HUD }, unrankedText = new OsuSpriteText { - AlwaysPresent = true, Anchor = Anchor.BottomCentre, Origin = Anchor.TopCentre, Text = @"/ UNRANKED /", @@ -77,7 +80,7 @@ namespace osu.Game.Screens.Play.HUD private void appearTransform() { - if (mods.Value.Any(m => !m.Ranked)) + if (DisplayUnrankedText && mods.Value.Any(m => !m.Ranked)) unrankedText.FadeInFromZero(fade_duration, Easing.OutQuint); else unrankedText.Hide(); From d86cbf66a9ad7c00824ad6cb5dd6b97b7e246dbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Dec 2018 13:10:47 +0700 Subject: [PATCH 118/355] Update docstring Co-Authored-By: pavlukivan --- osu.Game/Rulesets/Objects/HitWindows.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index e4d987e2dc..841452df55 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -58,7 +58,8 @@ namespace osu.Game.Rulesets.Objects /// /// Whether it's possible to achieve this . /// - /// The result. + /// The result type to check. + /// Whether the can be achieved. public virtual bool IsHitResultAllowed(HitResult result) { switch (result) From ffb91b4afcef7d668ffeb0e3d6d0d88d12274dfd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Dec 2018 13:11:03 +0700 Subject: [PATCH 119/355] Update docstring Co-Authored-By: pavlukivan --- osu.Game/Rulesets/Objects/HitWindows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 841452df55..c75e914d2d 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Objects protected virtual HitResult SuccessfulHitResult => HitResult.Meh; /// - /// Whether it's possible to achieve this . + /// Check whether it is possible to achieve the provided . /// /// The result type to check. /// Whether the can be achieved. From e49e2fda9e3fdd8488a70010e3bd36e3a2d045c2 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Wed, 12 Dec 2018 13:24:58 +0700 Subject: [PATCH 120/355] Rename SuccessfulHitResult->LowestSuccessfulHitResult --- osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs | 2 +- osu.Game/Rulesets/Objects/HitWindows.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index 2317d4cc90..2c207114da 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Objects { HitResult.Miss, (270, 190, 140) }, }; - protected override HitResult SuccessfulHitResult => HitResult.Good; + protected override HitResult LowestSuccessfulHitResult => HitResult.Good; public override bool IsHitResultAllowed(HitResult result) { diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index c75e914d2d..cf8769a105 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Objects /// /// The with the largest hit window that produces a successful hit. /// - protected virtual HitResult SuccessfulHitResult => HitResult.Meh; + protected virtual HitResult LowestSuccessfulHitResult => HitResult.Meh; /// /// Check whether it is possible to achieve the provided . @@ -137,6 +137,6 @@ namespace osu.Game.Rulesets.Objects /// /// The time offset. /// Whether the can be hit at any point in the future from this time offset. - public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(SuccessfulHitResult); + public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(LowestSuccessfulHitResult); } } From 439d741dee62f95c67547afe116c858d1c28e484 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 16:06:56 +0900 Subject: [PATCH 121/355] Implement basic api structure for rooms --- osu.Game/Online/Multiplayer/Room.cs | 92 ++++++++++++++++++++++++++++- osu.Game/Rulesets/Mods/IMod.cs | 3 + 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 67ddb60823..71668e4c4b 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -3,16 +3,28 @@ using System.Collections.Generic; using System.Linq; +using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Users; namespace osu.Game.Online.Multiplayer { public class Room { - public Bindable Name = new Bindable("My awesome room!"); - public Bindable Host = new Bindable(); + public Bindable RoomID { get; } = new Bindable(); + + [JsonProperty("name")] + public readonly Bindable Name = new Bindable("My awesome room!"); + + [JsonProperty("host")] + public readonly Bindable Host = new Bindable(); + + [JsonProperty("playlist")] + public readonly BindableCollection Playlist = new BindableCollection(); + public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); public Bindable Type = new Bindable(new GameTypeTimeshift()); @@ -20,6 +32,82 @@ namespace osu.Game.Online.Multiplayer public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(Enumerable.Empty()); + public void CopyFrom(Room other) + { + Name.Value = other.Name; + Host.Value = other.Host; + Status.Value = other.Status; + Availability.Value = other.Availability; + Type.Value = other.Type; + Beatmap.Value = other.Beatmap; + MaxParticipants.Value = other.MaxParticipants; + Participants.Value = other.Participants.Value.ToArray(); + } + public Bindable Created = new Bindable(); } + + public class PlaylistItem + { + [JsonProperty("beatmap")] + public BeatmapInfo Beatmap; + + [JsonProperty("ruleset_id")] + public int RulesetID { get; set; } + + public readonly BindableCollection AllowedMods = new BindableCollection(); + + public readonly BindableCollection RequiredMods = new BindableCollection(); + + private APIMod[] _allowedMods; + + [JsonProperty("allowed_mods")] + private APIMod[] allowedMods + { + get => AllowedMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); + set => _allowedMods = value; + } + + private APIMod[] _requiredMods; + + [JsonProperty("required_mods")] + private APIMod[] requiredMods + { + get => RequiredMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); + set => _requiredMods = value; + } + + private RulesetInfo ruleset; + + public RulesetInfo Ruleset + { + get => ruleset; + set + { + ruleset = value; + + if (_allowedMods != null) + { + AllowedMods.Clear(); + AllowedMods.AddRange(value.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); + + _allowedMods = null; + } + + if (_requiredMods != null) + { + RequiredMods.Clear(); + RequiredMods.AddRange(value.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); + + _requiredMods = null; + } + } + } + + // Todo: Move this elsewhere for reusability + private class APIMod : IMod + { + public string Acronym { get; set; } + } + } } diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index d0c4ce2f4c..4a95ce8111 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.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 Newtonsoft.Json; + namespace osu.Game.Rulesets.Mods { public interface IMod @@ -8,6 +10,7 @@ namespace osu.Game.Rulesets.Mods /// /// The shortened name of this mod. /// + [JsonProperty] string Acronym { get; } } } From 6123a11b67b6425606d45889807f9fdecdf83c1c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 16:20:11 +0900 Subject: [PATCH 122/355] Use RoomID for creation --- osu.Game/Online/Multiplayer/Room.cs | 5 ++--- osu.Game/Screens/Multi/Match/Components/Header.cs | 6 +++--- .../Screens/Multi/Match/Components/MatchTabControl.cs | 8 ++++---- osu.Game/Screens/Multi/RoomManager.cs | 1 - 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 71668e4c4b..6dae9d2d74 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Multiplayer { public class Room { - public Bindable RoomID { get; } = new Bindable(); + public Bindable RoomID { get; } = new Bindable(); [JsonProperty("name")] public readonly Bindable Name = new Bindable("My awesome room!"); @@ -34,6 +34,7 @@ namespace osu.Game.Online.Multiplayer public void CopyFrom(Room other) { + RoomID.Value = other.RoomID; Name.Value = other.Name; Host.Value = other.Host; Status.Value = other.Status; @@ -43,8 +44,6 @@ namespace osu.Game.Online.Multiplayer MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); } - - public Bindable Created = new Bindable(); } public class PlaylistItem diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 9c72403806..b5ae3baa15 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Multi.Match.Components private class BeatmapSelectButton : TriangleButton { - private readonly IBindable createdBind = new Bindable(); + private readonly IBindable roomIDBind = new Bindable(); [Resolved] private Room room { get; set; } @@ -113,8 +113,8 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - createdBind.BindTo(room.Created); - createdBind.BindValueChanged(v => Enabled.Value = !v, true); + roomIDBind.BindTo(room.RoomID); + roomIDBind.BindValueChanged(v => Enabled.Value = !v.HasValue, true); } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs index 51698fa50f..fa760c97e3 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -14,7 +14,7 @@ namespace osu.Game.Screens.Multi.Match.Components { public class MatchTabControl : PageTabControl { - private readonly IBindable created = new Bindable(); + private readonly IBindable roomIdBind = new Bindable(); [Resolved] private Room room { get; set; } @@ -28,10 +28,10 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - created.BindTo(room.Created); - created.BindValueChanged(v => + roomIdBind.BindTo(room.RoomID); + roomIdBind.BindValueChanged(v => { - if (v) + if (v.HasValue) { Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage)); Current.Value = new RoomMatchPage(); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 9e233f278b..e2d132b8bb 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -25,7 +25,6 @@ namespace osu.Game.Screens.Multi // Todo: Perform API request - room.Created.Value = true; rooms.Add(room); } } From 77e0d7ed8e3ecc799387c5d2096183ca5269ff88 Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Wed, 12 Dec 2018 07:57:37 +0000 Subject: [PATCH 123/355] Fix formatting --- .../Judgements/TaikoDrumRollTickJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 86b495ca08..e11bdf225f 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements protected override double HealthIncreaseFor(HitResult result) { - switch(result) + switch (result) { case HitResult.Great: return 0.15; From 87ebb00f1c5787a0a1629eac9b0a5c8f48d4a035 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 19:03:27 +0900 Subject: [PATCH 124/355] Make Target abstract (should absolutely always be set) --- osu.Game/Online/API/APIRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index adbedb2aac..baa5ab3267 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -40,7 +40,7 @@ namespace osu.Game.Online.API /// public int Timeout = WebRequest.DEFAULT_TIMEOUT; - protected virtual string Target => string.Empty; + protected abstract string Target { get; } protected virtual WebRequest CreateWebRequest() => new WebRequest(Uri); From 450e4cd2235a6250245f9336f9c22ec16eca7982 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 19:04:11 +0900 Subject: [PATCH 125/355] Hook up API --- osu.Game.Tests/Visual/TestCaseDrawableRoom.cs | 135 ------------ osu.Game.Tests/Visual/TestCaseLounge.cs | 208 ------------------ osu.Game.Tests/Visual/TestCaseMatch.cs | 152 ------------- .../Visual/TestCaseRoomInspector.cs | 141 ------------ osu.Game/Online/Multiplayer/Room.cs | 45 +++- osu.Game/Overlays/Music/PlaylistItem.cs | 1 + osu.Game/Screens/Multi/RoomManager.cs | 105 ++++++++- 7 files changed, 144 insertions(+), 643 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseDrawableRoom.cs delete mode 100644 osu.Game.Tests/Visual/TestCaseLounge.cs delete mode 100644 osu.Game.Tests/Visual/TestCaseMatch.cs delete mode 100644 osu.Game.Tests/Visual/TestCaseRoomInspector.cs diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs deleted file mode 100644 index bcebf0a8d9..0000000000 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Lounge.Components; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseDrawableRoom : OsuTestCase - { - private RulesetStore rulesets; - - protected override void LoadComplete() - { - base.LoadComplete(); - - DrawableRoom first; - Add(new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Y, - Width = 580f, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - first = new DrawableRoom(new Room - { - Name = { Value = @"Great Room Right Here" }, - Host = { Value = new User { Username = @"Naeferith", Id = 9492835, Country = new Country { FlagName = @"FR" } } }, - Status = { Value = new RoomStatusOpen() }, - Type = { Value = new GameTypeTeamVersus() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 4.65, - Ruleset = rulesets.GetRuleset(3), - Metadata = new BeatmapMetadata - { - Title = @"Critical Crystal", - Artist = @"Seiryu", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh//beatmaps/376340/covers/cover.jpg?1456478455", - }, - }, - }, - }, - }, - Participants = - { - Value = new[] - { - new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1355 } } }, - new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 8756 } } }, - }, - }, - }), - new DrawableRoom(new Room - { - Name = { Value = @"Relax It's The Weekend" }, - Host = { Value = new User { Username = @"peppy", Id = 2, Country = new Country { FlagName = @"AU" } } }, - Status = { Value = new RoomStatusPlaying() }, - Type = { Value = new GameTypeTagTeam() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 1.96, - Ruleset = rulesets.GetRuleset(0), - Metadata = new BeatmapMetadata - { - Title = @"Serendipity", - Artist = @"ZAQ", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh//beatmaps/526839/covers/cover.jpg?1493815706", - }, - }, - }, - }, - }, - Participants = - { - Value = new[] - { - new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 578975 } } }, - new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24554 } } }, - }, - }, - }), - } - }); - - AddStep(@"select", () => first.State = SelectionState.Selected); - AddStep(@"change title", () => first.Room.Name.Value = @"I Changed Name"); - AddStep(@"change host", () => first.Room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } }); - AddStep(@"change status", () => first.Room.Status.Value = new RoomStatusPlaying()); - AddStep(@"change type", () => first.Room.Type.Value = new GameTypeVersus()); - AddStep(@"change beatmap", () => first.Room.Beatmap.Value = null); - AddStep(@"change participants", () => first.Room.Participants.Value = new[] - { - new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1254 } } }, - new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 123189 } } }, - }); - AddStep(@"deselect", () => first.State = SelectionState.NotSelected); - } - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - this.rulesets = rulesets; - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseLounge.cs b/osu.Game.Tests/Visual/TestCaseLounge.cs deleted file mode 100644 index c1253e4f5c..0000000000 --- a/osu.Game.Tests/Visual/TestCaseLounge.cs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; -using osu.Game.Screens; -using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Lounge; -using osu.Game.Screens.Multi.Lounge.Components; -using osu.Game.Users; -using osuTK.Input; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseLounge : ManualInputManagerTestCase - { - private TestLoungeScreen loungeScreen; - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - loungeScreen = new TestLoungeScreen(); - - Room[] rooms = - { - new Room - { - Name = { Value = @"Just Another Room" }, - Host = { Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } } }, - Status = { Value = new RoomStatusPlaying() }, - Availability = { Value = RoomAvailability.Public }, - Type = { Value = new GameTypeTagTeam() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 5.65, - Ruleset = rulesets.GetRuleset(0), - Metadata = new BeatmapMetadata - { - Title = @"Sidetracked Day (Short Ver.)", - Artist = @"VINXIS", - AuthorString = @"Hobbes2", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/767600/covers/cover.jpg?1526243446", - }, - }, - }, - } - }, - MaxParticipants = { Value = 10 }, - Participants = - { - Value = new[] - { - new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } }, - new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } }, - new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } }, - new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } }, - new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } }, - new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } }, - } - } - }, - new Room - { - Name = { Value = @"Not Just Any Room" }, - Host = { Value = new User { Username = @"Monstrata", Id = 2706438, Country = new Country { FlagName = @"CA" } } }, - Status = { Value = new RoomStatusOpen() }, - Availability = { Value = RoomAvailability.FriendsOnly }, - Type = { Value = new GameTypeTeamVersus() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 2.73, - Ruleset = rulesets.GetRuleset(0), - Metadata = new BeatmapMetadata - { - Title = @"lit(var)", - Artist = @"kensuke ushio", - AuthorString = @"Monstrata", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/623972/covers/cover.jpg?1521167183", - }, - }, - }, - } - }, - Participants = - { - Value = new[] - { - new User { Username = @"Jeby", Id = 3136279, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 3497 } } }, - new User { Username = @"DualAkira", Id = 5220933, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 643 } } }, - new User { Username = @"Datenshi Yohane", Id = 7171857, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10555 } } }, - } - } - }, - new Room - { - Name = { Value = @"room THE FINAL" }, - Host = { Value = new User { Username = @"Delis", Id = 1603923, Country = new Country { FlagName = @"JP" } } }, - Status = { Value = new RoomStatusPlaying() }, - Availability = { Value = RoomAvailability.Public }, - Type = { Value = new GameTypeTagTeam() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 4.48, - Ruleset = rulesets.GetRuleset(3), - Metadata = new BeatmapMetadata - { - Title = @"ONIGIRI FREEWAY", - Artist = @"OISHII", - AuthorString = @"Mentholzzz", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/663098/covers/cover.jpg?1521898837", - }, - }, - }, - } - }, - MaxParticipants = { Value = 30 }, - Participants = - { - Value = new[] - { - new User { Username = @"KizuA", Id = 6510442, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 5372 } } }, - new User { Username = @"Colored", Id = 827563, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 810 } } }, - new User { Username = @"Beryl", Id = 3817591, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10096 } } }, - } - } - }, - }; - - AddStep(@"show", () => Add(loungeScreen)); - selectAssert(0); - AddAssert(@"no room selected", () => loungeScreen.SelectedRoom == null); - selectAssert(1); - AddStep(@"open room 1", () => clickRoom(1)); - AddUntilStep(() => loungeScreen.ChildScreen?.IsCurrentScreen == true, "wait until room current"); - AddStep(@"make lounge current", loungeScreen.MakeCurrent); - filterAssert(@"THE FINAL", LoungeTab.Public, 1); - filterAssert(string.Empty, LoungeTab.Public, 2); - filterAssert(string.Empty, LoungeTab.Private, 1); - filterAssert(string.Empty, LoungeTab.Public, 2); - filterAssert(@"no matches", LoungeTab.Public, 0); - filterAssert(string.Empty, LoungeTab.Public, 2); - AddStep(@"exit", loungeScreen.Exit); - } - - private void clickRoom(int n) - { - InputManager.Click(MouseButton.Left); - } - - private void selectAssert(int n) - { - AddStep($@"select room {n}", () => clickRoom(n)); - } - - private void filterAssert(string filter, LoungeTab tab, int endCount) - { - AddStep($@"filter '{filter}', {tab}", () => loungeScreen.SetFilter(filter, tab)); - } - - private class TestLoungeScreen : LoungeScreen - { - protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); - - [Resolved] - private RoomManager manager { get; set; } - - public Room SelectedRoom => manager.Current.Value; - - public void SetFilter(string filter, LoungeTab tab) - { - Filter.Search.Current.Value = filter; - Filter.Tabs.Current.Value = tab; - } - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs deleted file mode 100644 index fd4806ac90..0000000000 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ /dev/null @@ -1,152 +0,0 @@ -// 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 NUnit.Framework; -using osu.Framework.Allocation; -using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Match; -using osu.Game.Screens.Multi.Match.Components; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseMatch : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(TestCaseMatch), - typeof(GameTypePicker), - typeof(RoomSettingsOverlay) - }; - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - Room room = new Room - { - Name = { Value = @"One Awesome Room" }, - Status = { Value = new RoomStatusOpen() }, - Availability = { Value = RoomAvailability.Public }, - Type = { Value = new GameTypeTeamVersus() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 5.02, - Ruleset = rulesets.GetRuleset(1), - Metadata = new BeatmapMetadata - { - Title = @"Paradigm Shift", - Artist = @"Morimori Atsushi", - AuthorString = @"eiri-", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/765055/covers/cover.jpg?1526955337", - }, - }, - }, - }, - }, - MaxParticipants = { Value = 5 }, - Participants = - { - Value = new[] - { - new User - { - Username = @"eiri-", - Id = 3388410, - Country = new Country { FlagName = @"US" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/3388410/00a8486a247831e1cc4375db519f611ac970bda8bc0057d78b0f540ea38c3e58.jpeg", - IsSupporter = true, - }, - new User - { - Username = @"Nepuri", - Id = 6637817, - Country = new Country { FlagName = @"DE" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/6637817/9085fc60248b6b5327a72c1dcdecf2dbedba810ae0ab6bcf7224e46b1339632a.jpeg", - IsSupporter = true, - }, - new User - { - Username = @"goheegy", - Id = 8057655, - Country = new Country { FlagName = @"GB" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8057655/21cec27c25a11dc197a4ec6a74253dbabb495949b0e0697113352f12007018c5.jpeg", - }, - new User - { - Username = @"Alumetri", - Id = 5371497, - Country = new Country { FlagName = @"RU" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/5371497/e023b8c7fbe3613e64bd4856703517ea50fbed8a5805dc9acda9efe9897c67e2.jpeg", - }, - } - }, - }; - - MatchScreen matchScreen = new MatchScreen(room); - - AddStep(@"show", () => Add(matchScreen)); - AddStep(@"null beatmap", () => room.Beatmap.Value = null); - AddStep(@"change name", () => room.Name.Value = @"Two Awesome Rooms"); - AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); - AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.FriendsOnly); - AddStep(@"change type", () => room.Type.Value = new GameTypeTag()); - AddStep(@"change beatmap", () => room.Beatmap.Value = new BeatmapInfo - { - StarDifficulty = 4.33, - Ruleset = rulesets.GetRuleset(2), - Metadata = new BeatmapMetadata - { - Title = @"Yasashisa no Riyuu", - Artist = @"ChouCho", - AuthorString = @"celerih", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/685391/covers/cover.jpg?1524597970", - }, - }, - }, - }); - - AddStep(@"null max participants", () => room.MaxParticipants.Value = null); - AddStep(@"change participants", () => room.Participants.Value = new[] - { - new User - { - Username = @"Spectator", - Id = 702598, - Country = new Country { FlagName = @"KR" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/702598/3bbf4cb8b8d2cf8b03145000a975ff27e191ab99b0920832e7dd67386280e288.jpeg", - IsSupporter = true, - }, - new User - { - Username = @"celerih", - Id = 4696296, - Country = new Country { FlagName = @"CA" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/4696296/7f8500731d0ac66d5472569d146a7be07d9460273361913f22c038867baddaef.jpeg", - }, - }); - - AddStep(@"exit", matchScreen.Exit); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs deleted file mode 100644 index 9f6eea68e7..0000000000 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Lounge.Components; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseRoomInspector : OsuTestCase - { - private RulesetStore rulesets; - - protected override void LoadComplete() - { - base.LoadComplete(); - - Room room = new Room - { - Name = { Value = @"My Awesome Room" }, - Host = { Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" } } }, - Status = { Value = new RoomStatusOpen() }, - Type = { Value = new GameTypeTeamVersus() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 3.7, - Ruleset = rulesets.GetRuleset(3), - Metadata = new BeatmapMetadata - { - Title = @"Platina", - Artist = @"Maaya Sakamoto", - AuthorString = @"uwutm8", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/560573/covers/cover.jpg?1492722343", - }, - }, - }, - } - }, - MaxParticipants = { Value = 200 }, - Participants = - { - Value = new[] - { - new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } }, - new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } }, - new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } }, - new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } }, - new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } }, - new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } }, - } - } - }; - - Add(new RoomInspector - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Width = 0.5f, - }); - - AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above"); - AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } }); - AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); - AddStep(@"change type", () => room.Type.Value = new GameTypeTag()); - AddStep(@"change beatmap", () => room.Beatmap.Value = null); - AddStep(@"change max participants", () => room.MaxParticipants.Value = null); - AddStep(@"change participants", () => room.Participants.Value = new[] - { - new User { Username = @"filsdelama", Id = 2831793, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 854 } } }, - new User { Username = @"_index", Id = 652457, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 150 } } } - }); - - AddStep(@"change room", () => - { - Room newRoom = new Room - { - Name = { Value = @"My New, Better Than Ever Room" }, - Host = { Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" } } }, - Status = { Value = new RoomStatusOpen() }, - Type = { Value = new GameTypeTagTeam() }, - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 7.07, - Ruleset = rulesets.GetRuleset(0), - Metadata = new BeatmapMetadata - { - Title = @"FREEDOM DIVE", - Artist = @"xi", - AuthorString = @"Nakagawa-Kanon", - }, - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new BeatmapSetOnlineInfo - { - Covers = new BeatmapSetOnlineCovers - { - Cover = @"https://assets.ppy.sh/beatmaps/39804/covers/cover.jpg?1456506845", - }, - }, - }, - }, - }, - MaxParticipants = { Value = 10 }, - Participants = - { - Value = new[] - { - new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 4 } } }, - new User { Username = @"HappyStick", Id = 256802, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 752 } } }, - new User { Username = @"-Konpaku-", Id = 2258797, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 571 } } } - } - } - }; - }); - } - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - this.rulesets = rulesets; - } - } -} diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 6dae9d2d74..56c4585b2a 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -6,6 +6,7 @@ using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; @@ -14,24 +15,44 @@ namespace osu.Game.Online.Multiplayer { public class Room { + [JsonProperty("id")] public Bindable RoomID { get; } = new Bindable(); + [JsonIgnore] + public readonly Bindable Beatmap = new Bindable(); + [JsonProperty("name")] public readonly Bindable Name = new Bindable("My awesome room!"); [JsonProperty("host")] public readonly Bindable Host = new Bindable(); + public bool ShouldSerializeHost() => false; + [JsonProperty("playlist")] public readonly BindableCollection Playlist = new BindableCollection(); + [JsonProperty("duration")] + public readonly Bindable Duration = new Bindable(100); + + [JsonProperty("max_attempts")] + public readonly Bindable MaxAttempts = new Bindable(null); + public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); public Bindable Type = new Bindable(new GameTypeTimeshift()); - public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(Enumerable.Empty()); + public Room() + { + Beatmap.BindValueChanged(b => + { + Playlist.Clear(); + Playlist.Add(new PlaylistItem { Beatmap = b }); + }); + } + public void CopyFrom(Room other) { RoomID.Value = other.RoomID; @@ -40,22 +61,34 @@ namespace osu.Game.Online.Multiplayer Status.Value = other.Status; Availability.Value = other.Availability; Type.Value = other.Type; - Beatmap.Value = other.Beatmap; MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); + + // Temp: + Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap; } } public class PlaylistItem { [JsonProperty("beatmap")] - public BeatmapInfo Beatmap; + private APIBeatmap beatmap { get; set; } + + public bool ShouldSerializebeatmap() => false; + + [JsonIgnore] + public BeatmapInfo Beatmap { get; set; } + + [JsonProperty("beatmap_id")] + public int BeatmapID => 847296; //Beatmap.OnlineBeatmapID ?? 0; [JsonProperty("ruleset_id")] public int RulesetID { get; set; } + [JsonIgnore] public readonly BindableCollection AllowedMods = new BindableCollection(); + [JsonIgnore] public readonly BindableCollection RequiredMods = new BindableCollection(); private APIMod[] _allowedMods; @@ -78,6 +111,7 @@ namespace osu.Game.Online.Multiplayer private RulesetInfo ruleset; + [JsonIgnore] public RulesetInfo Ruleset { get => ruleset; @@ -103,6 +137,11 @@ namespace osu.Game.Online.Multiplayer } } + public void SetRulesets(RulesetStore rulesets) + { + Beatmap = beatmap.ToBeatmap(rulesets); + } + // Todo: Move this elsewhere for reusability private class APIMod : IMod { diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index b4828e41f6..9368bee81c 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -8,6 +8,7 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index e2d132b8bb..fead90f9a2 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -1,15 +1,24 @@ // 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 System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.Graphics; +using osu.Framework.IO.Network; +using osu.Framework.Logging; +using osu.Game.Beatmaps; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; namespace osu.Game.Screens.Multi { - public class RoomManager : Component + public class RoomManager : PollingComponent { public IBindableCollection Rooms => rooms; private readonly BindableCollection rooms = new BindableCollection(); @@ -19,13 +28,101 @@ namespace osu.Game.Screens.Multi [Resolved] private APIAccess api { get; set; } + [Resolved] + private RulesetStore rulesets { get; set; } + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + public RoomManager() + { + TimeBetweenPolls = 5000; + } + public void CreateRoom(Room room) { room.Host.Value = api.LocalUser; - // Todo: Perform API request + var req = new CreateRoomRequest(room); - rooms.Add(room); + req.Success += result => addRoom(room, result); + req.Failure += exception => Logger.Log($"Failed to create room: {exception}"); + api.Queue(req); + } + + protected override Task Poll() + { + if (!api.IsLoggedIn) + return base.Poll(); + + var tcs = new TaskCompletionSource(); + + var pollReq = new GetRoomsRequest(); + + pollReq.Success += result => + { + foreach (var r in result) + { + foreach (var pi in r.Playlist) + { + pi.Ruleset = rulesets.GetRuleset(pi.RulesetID); + pi.SetRulesets(rulesets); + } + + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == r.RoomID.Value); + if (existing == null) + rooms.Add(r); + else + existing.CopyFrom(r); + } + + tcs.SetResult(true); + }; + + pollReq.Failure += _ => tcs.SetResult(false); + + api.Queue(pollReq); + + return tcs.Task; + } + + private void addRoom(Room local, Room remote) + { + local.CopyFrom(remote); + + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == local.RoomID.Value); + if (existing != null) + rooms.Remove(existing); + rooms.Add(local); + } + + private class CreateRoomRequest : APIRequest + { + private readonly Room room; + + public CreateRoomRequest(Room room) + { + this.room = room; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.ContentType = "application/json"; + req.Method = HttpMethod.Post; + + req.AddRaw(JsonConvert.SerializeObject(room)); + + return req; + } + + protected override string Target => "rooms"; + } + + private class GetRoomsRequest : APIRequest> + { + protected override string Target => "rooms"; } } } From 28b033bd993d19ff50462d0ce8dea2c06b71febd Mon Sep 17 00:00:00 2001 From: Ivan Pavluk Date: Wed, 12 Dec 2018 17:15:59 +0700 Subject: [PATCH 126/355] Autodetect LowestSuccessfulHitResult --- .../Objects/TaikoHitWindows.cs | 2 -- osu.Game/Rulesets/Objects/HitWindows.cs | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index 2c207114da..9199e6f141 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { HitResult.Miss, (270, 190, 140) }, }; - protected override HitResult LowestSuccessfulHitResult => HitResult.Good; - public override bool IsHitResultAllowed(HitResult result) { switch (result) diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index cf8769a105..40fb98a997 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -51,9 +51,19 @@ namespace osu.Game.Rulesets.Objects public double Miss { get; protected set; } /// - /// The with the largest hit window that produces a successful hit. + /// Retrieves the with the largest hit window that produces a successful hit. /// - protected virtual HitResult LowestSuccessfulHitResult => HitResult.Meh; + /// The lowest allowed successful . + protected HitResult LowestSuccessfulHitResult() + { + for (var result = HitResult.Meh; result <= HitResult.Perfect; ++result) + { + if (IsHitResultAllowed(result)) + return result; + } + + return HitResult.None; + } /// /// Check whether it is possible to achieve the provided . @@ -137,6 +147,6 @@ namespace osu.Game.Rulesets.Objects /// /// The time offset. /// Whether the can be hit at any point in the future from this time offset. - public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(LowestSuccessfulHitResult); + public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(LowestSuccessfulHitResult()); } } From bac4f42eac5015c9b20edc22933138fcf4b95f03 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Dec 2018 19:34:37 +0900 Subject: [PATCH 127/355] Fix backgrounds not quite working --- .../UpdateableBeatmapBackgroundSprite.cs | 17 ++++++++++++----- .../Online/API/Requests/Responses/APIBeatmap.cs | 6 +----- osu.Game/Online/Multiplayer/Room.cs | 3 --- .../Multi/Lounge/Components/DrawableRoom.cs | 3 +-- .../Multi/Lounge/Components/RoomInspector.cs | 2 +- .../Screens/Multi/Match/Components/Header.cs | 2 +- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- osu.Game/Screens/Multi/RoomManager.cs | 3 +++ 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 5ced21e436..0a9726b121 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -9,21 +9,28 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Beatmaps.Drawables { - public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable + public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable { - public readonly IBindable Beatmap = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); [Resolved] - private OsuGameBase game { get; set; } + private BeatmapManager beatmaps { get; set; } public UpdateableBeatmapBackgroundSprite() { Beatmap.BindValueChanged(b => Schedule(() => Model = b)); } - protected override Drawable CreateDrawable(WorkingBeatmap model) + protected override Drawable CreateDrawable(BeatmapInfo model) { - Drawable drawable = model == null ? (Drawable)new DefaultSprite() : new BeatmapBackgroundSprite(model); + Drawable drawable; + + if (model == null) + drawable = new DefaultSprite(); + else if (model.BeatmapSet?.OnlineInfo != null) + drawable = new BeatmapSetCover(model.BeatmapSet); + else + drawable = new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(model)); drawable.RelativeSizeAxes = Axes.Both; drawable.Anchor = Anchor.Centre; diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 193ccf1f6b..b96e4bedf6 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -67,11 +67,7 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapID = OnlineBeatmapID, Version = version, Status = Status, - BeatmapSet = new BeatmapSetInfo - { - OnlineBeatmapSetID = OnlineBeatmapSetID, - Status = BeatmapSet?.Status ?? BeatmapSetOnlineStatus.None - }, + BeatmapSet = BeatmapSet.ToBeatmapSet(rulesets), BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 56c4585b2a..4af92f68ea 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -63,9 +63,6 @@ namespace osu.Game.Online.Multiplayer Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); - - // Temp: - Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap; } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 57ce9fc0b9..647913308d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -213,8 +213,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }; - background.Beatmap.BindTo(beatmap); - beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); nameBind.BindValueChanged(n => name.Text = n); @@ -224,6 +222,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components typeBind.BindTo(Room.Type); beatmapBind.BindTo(Room.Beatmap); participantsBind.BindTo(Room.Participants); + background.Beatmap.BindTo(beatmapBind); modeTypeInfo.Beatmap.BindTo(beatmapBind); modeTypeInfo.Type.BindTo(typeBind); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index e8de201b8f..5b796b5a3d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -180,7 +180,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components nameBind.BindValueChanged(n => name.Text = n); - background.Beatmap.BindTo(beatmap); + background.Beatmap.BindTo(beatmapBind); participantInfo.Host.BindTo(hostBind); participantInfo.Participants.BindTo(participantsBind); diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index b5ae3baa15..005378756e 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Multi.Match.Components { public const float HEIGHT = 200; - public readonly IBindable Beatmap = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); private readonly Box tabStrip; diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 755b071f30..a2a7c4e70d 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi.Match }; header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect()); - header.Beatmap.BindTo(Beatmap); + header.Beatmap.BindTo(beatmapBind); header.Tabs.Current.ValueChanged += t => { diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index fead90f9a2..d6c5a12d33 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -69,6 +69,9 @@ namespace osu.Game.Screens.Multi pi.SetRulesets(rulesets); } + // Temporarily + r.Beatmap.Value = r.Playlist.FirstOrDefault()?.Beatmap; + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == r.RoomID.Value); if (existing == null) rooms.Add(r); From ebd93757806d66e2a6cf7c6dc80d44a9c2073667 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Dec 2018 20:12:30 +0900 Subject: [PATCH 128/355] Add more tests --- .../Visual/TestCasePollingComponent.cs | 108 ++++++++++++------ 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/TestCasePollingComponent.cs index 928c92cb2b..a77a4a7d57 100644 --- a/osu.Game.Tests/Visual/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/TestCasePollingComponent.cs @@ -3,10 +3,11 @@ using System; using System.Threading.Tasks; -using osu.Framework.Allocation; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; using osu.Game.Graphics.Sprites; using osu.Game.Online; using osuTK; @@ -19,12 +20,16 @@ namespace osu.Game.Tests.Visual private Container pollBox; private TestPoller poller; - [BackgroundDependencyLoader] - private void load() + private const float safety_adjust = 1f; + private int count; + + [SetUp] + public void SetUp() => Schedule(() => { + count = 0; + Children = new Drawable[] { - poller = new TestPoller(), pollBox = new Container { Alpha = 0, @@ -48,41 +53,75 @@ namespace osu.Game.Tests.Visual } } }; + }); - int count = 0; + //[Test] + public void TestInstantPolling() + { + createPoller(true); + AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust); + checkCount(1); + checkCount(2); + checkCount(3); + + AddStep("set poll interval to 5", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust * 5); + checkCount(4); + checkCount(4); + checkCount(4); + + skip(); + + checkCount(5); + checkCount(5); + + AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust); + checkCount(6); + checkCount(7); + } + + [Test] + public void TestSlowPolling() + { + createPoller(false); + + AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust * 5); + checkCount(0); + skip(); + checkCount(0); + skip(); + skip(); + checkCount(0); + skip(); + skip(); + checkCount(0); + } + + private void skip() => AddStep("skip", () => + { + // could be 4 or 5 at this point due to timing discrepancies (safety_adjust @ 0.2 * 5 ~= 1) + // easiest to just ignore the value at this point and move on. + }); + + private void checkCount(int checkValue) + { + Logger.Log($"value is {count}"); + AddAssert($"count is {checkValue}", () => count == checkValue); + } + + private void createPoller(bool instant) => AddStep("create poller", () => + { + poller?.Expire(); + + Add(poller = instant ? new TestPoller() : new TestSlowPoller()); poller.OnPoll += () => { pollBox.FadeOutFromOne(500); count++; }; + }); - AddStep("set poll to 1 second", () => poller.TimeBetweenPolls = TimePerAction); - - void checkCount(int checkValue) => AddAssert($"count is {checkValue}", () => count == checkValue); - - checkCount(1); - checkCount(2); - checkCount(3); - - AddStep("set poll to 5 second", () => poller.TimeBetweenPolls = TimePerAction * 5); - - checkCount(4); - checkCount(4); - checkCount(4); - checkCount(4); - - checkCount(5); - checkCount(5); - checkCount(5); - - AddStep("set poll to 5 second", () => poller.TimeBetweenPolls = TimePerAction); - - AddAssert("count is 6", () => count == 6); - - } - - protected override double TimePerAction => 500; + protected override double TimePerAction => 500000; public class TestPoller : PollingComponent { @@ -90,9 +129,14 @@ namespace osu.Game.Tests.Visual protected override Task Poll() { - OnPoll?.Invoke(); + Schedule(() => OnPoll?.Invoke()); return base.Poll(); } } + + public class TestSlowPoller : TestPoller + { + protected override Task Poll() => Task.Delay((int)(TimeBetweenPolls / 2f / Clock.Rate)).ContinueWith(_ => base.Poll()); + } } } From 4fc9902cd2d7827122f90fcb1f4e4380124b4177 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Dec 2018 21:30:21 +0900 Subject: [PATCH 129/355] Fix reverting to default skin via settings button causing a hard crash --- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 23f35d5d3a..e259996b7f 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections public override FontAwesome Icon => FontAwesome.fa_paint_brush; - private readonly Bindable dropdownBindable = new Bindable(); + private readonly Bindable dropdownBindable = new Bindable { Default = SkinInfo.Default }; private readonly Bindable configBindable = new Bindable(); private SkinManager skins; From ac0fc6236c0cb2d552f21c0629995f87ed65ccb2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Dec 2018 14:51:18 +0900 Subject: [PATCH 130/355] Fix crash when changing beatmap toggles at loading screen --- osu.Game/Skinning/LocalSkinOverrideContainer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index 25d9442e6f..d7d2737d35 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -16,8 +16,8 @@ namespace osu.Game.Skinning { public event Action SourceChanged; - private Bindable beatmapSkins = new Bindable(); - private Bindable beatmapHitsounds = new Bindable(); + private readonly Bindable beatmapSkins = new Bindable(); + private readonly Bindable beatmapHitsounds = new Bindable(); public Drawable GetDrawableComponent(string componentName) { @@ -84,11 +84,8 @@ namespace osu.Game.Skinning [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - beatmapSkins = config.GetBindable(OsuSetting.BeatmapSkins); - beatmapSkins.BindValueChanged(_ => onSourceChanged()); - - beatmapHitsounds = config.GetBindable(OsuSetting.BeatmapHitsounds); - beatmapHitsounds.BindValueChanged(_ => onSourceChanged(), true); + config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); + config.BindWith(OsuSetting.BeatmapHitsounds, beatmapHitsounds); } protected override void LoadComplete() @@ -97,6 +94,9 @@ namespace osu.Game.Skinning if (fallbackSource != null) fallbackSource.SourceChanged += onSourceChanged; + + beatmapSkins.BindValueChanged(_ => onSourceChanged()); + beatmapHitsounds.BindValueChanged(_ => onSourceChanged(), true); } protected override void Dispose(bool isDisposing) From 264bd0e2aafd1283c1d7e45f5d8c5f0018260dc1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Dec 2018 16:06:30 +0900 Subject: [PATCH 131/355] Fix invalid room values --- osu.Game/Online/Multiplayer/Room.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 4af92f68ea..e2322db397 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -35,8 +35,16 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("duration")] public readonly Bindable Duration = new Bindable(100); - [JsonProperty("max_attempts")] - public readonly Bindable MaxAttempts = new Bindable(null); + [JsonIgnore] + public readonly Bindable MaxAttempts = new Bindable(); + + // Todo: Find a better way to do this (https://github.com/ppy/osu-framework/issues/1930) + [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] + private int? maxAttempts + { + get => MaxAttempts; + set => MaxAttempts.Value = value; + } public Bindable Status = new Bindable(new RoomStatusOpen()); public Bindable Availability = new Bindable(); From 71e5ce59da01307d444712e0176193d91b5def0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Dec 2018 16:17:24 +0900 Subject: [PATCH 132/355] Fix crash on exiting player during results transition --- osu.Game/Screens/Play/Player.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bf44e9e636..19b49b099c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -170,7 +170,7 @@ namespace osu.Game.Screens.Play { Retries = RestartCount, OnRetry = Restart, - OnQuit = Exit, + OnQuit = performUserRequestedExit, CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, Children = new[] { @@ -211,7 +211,7 @@ namespace osu.Game.Screens.Play failOverlay = new FailOverlay { OnRetry = Restart, - OnQuit = Exit, + OnQuit = performUserRequestedExit, }, new HotkeyRetryOverlay { @@ -225,7 +225,7 @@ namespace osu.Game.Screens.Play } }; - hudOverlay.HoldToQuit.Action = Exit; + hudOverlay.HoldToQuit.Action = performUserRequestedExit; hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded); RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); @@ -250,8 +250,16 @@ namespace osu.Game.Screens.Play mod.ApplyToClock(sourceClock); } + private void performUserRequestedExit() + { + if (!IsCurrentScreen) return; + Exit(); + } + public void Restart() { + if (!IsCurrentScreen) return; + sampleRestart?.Play(); ValidForResume = false; RestartRequested?.Invoke(); From 680a3e2aa4ad88e875b3843d290aceaa0c44bbec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 13 Dec 2018 18:38:03 +0900 Subject: [PATCH 133/355] Update with proper playlist usage --- .../UpdateableBeatmapBackgroundSprite.cs | 2 +- osu.Game/Online/Multiplayer/Room.cs | 12 ----- .../Multi/Lounge/Components/DrawableRoom.cs | 32 ++++++++---- .../Multi/Lounge/Components/RoomInspector.cs | 23 +++++--- .../Screens/Multi/Match/Components/Header.cs | 2 +- .../Match/Components/RoomSettingsOverlay.cs | 7 ++- osu.Game/Screens/Multi/Match/MatchScreen.cs | 52 +++++++++++++++---- osu.Game/Screens/Multi/RoomManager.cs | 3 -- 8 files changed, 87 insertions(+), 46 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 0a9726b121..15b89d27bd 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.Drawables { public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable { - public readonly IBindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); [Resolved] private BeatmapManager beatmaps { get; set; } diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index e2322db397..5e9fc4f008 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -18,9 +18,6 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("id")] public Bindable RoomID { get; } = new Bindable(); - [JsonIgnore] - public readonly Bindable Beatmap = new Bindable(); - [JsonProperty("name")] public readonly Bindable Name = new Bindable("My awesome room!"); @@ -52,15 +49,6 @@ namespace osu.Game.Online.Multiplayer public Bindable MaxParticipants = new Bindable(); public Bindable> Participants = new Bindable>(Enumerable.Empty()); - public Room() - { - Beatmap.BindValueChanged(b => - { - Playlist.Clear(); - Playlist.Add(new PlaylistItem { Beatmap = b }); - }); - } - public void CopyFrom(Room other) { RoomID.Value = other.RoomID; diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 647913308d..c425f8ef0a 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -39,14 +40,18 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly Box selectionBox; private readonly Bindable nameBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly IBindableCollection playlistBind = new BindableCollection(); private readonly Bindable beatmap = new Bindable(); + private UpdateableBeatmapBackgroundSprite background; + private BeatmapTitle beatmapTitle; + private ModeTypeInfo modeTypeInfo; + [Resolved] private BeatmapManager beatmaps { get; set; } @@ -104,11 +109,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void load(OsuColour colours) { Box sideStrip; - UpdateableBeatmapBackgroundSprite background; OsuSpriteText status; ParticipantInfo participantInfo; - BeatmapTitle beatmapTitle; - ModeTypeInfo modeTypeInfo; + OsuSpriteText name; Children = new Drawable[] @@ -213,24 +216,24 @@ namespace osu.Game.Screens.Multi.Lounge.Components d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }; - beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); nameBind.BindValueChanged(n => name.Text = n); nameBind.BindTo(Room.Name); hostBind.BindTo(Room.Host); statusBind.BindTo(Room.Status); typeBind.BindTo(Room.Type); - beatmapBind.BindTo(Room.Beatmap); + playlistBind.BindTo(Room.Playlist); participantsBind.BindTo(Room.Participants); - background.Beatmap.BindTo(beatmapBind); - modeTypeInfo.Beatmap.BindTo(beatmapBind); modeTypeInfo.Type.BindTo(typeBind); participantInfo.Host.BindTo(hostBind); participantInfo.Participants.BindTo(participantsBind); - beatmapTitle.Beatmap.BindTo(beatmapBind); + playlistBind.ItemsAdded += _ => updatePlaylist(); + playlistBind.ItemsRemoved += _ => updatePlaylist(); + + updatePlaylist(); } protected override void LoadComplete() @@ -238,5 +241,16 @@ namespace osu.Game.Screens.Multi.Lounge.Components base.LoadComplete(); this.FadeInFromZero(transition_duration); } + + private void updatePlaylist() + { + // For now, only the first playlist item is supported + var item = playlistBind.First(); + + beatmap.Value = beatmaps.GetWorkingBeatmap(item.Beatmap); + background.Beatmap.Value = item.Beatmap; + modeTypeInfo.Beatmap.Value = item.Beatmap; + beatmapTitle.Beatmap.Value = item.Beatmap; + } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 5b796b5a3d..1a2ff4c3d8 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -32,12 +32,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable hostBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly IBindableCollection playlistBind = new BindableCollection(); private readonly Bindable beatmap = new Bindable(); @@ -174,14 +174,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, }; + playlistBind.ItemsAdded += _ => updatePlaylist(); + playlistBind.ItemsRemoved += _ => updatePlaylist(); + statusBind.BindValueChanged(displayStatus); - beatmapBind.BindValueChanged(b => beatmap.Value = beatmaps.GetWorkingBeatmap(b)); participantsBind.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); nameBind.BindValueChanged(n => name.Text = n); - background.Beatmap.BindTo(beatmapBind); - participantInfo.Host.BindTo(hostBind); participantInfo.Participants.BindTo(participantsBind); @@ -189,7 +189,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components participantCount.MaxParticipants.BindTo(maxParticipantsBind); beatmapTypeInfo.Type.BindTo(typeBind); - beatmapTypeInfo.Beatmap.BindTo(beatmapBind); Room.BindValueChanged(updateRoom, true); } @@ -204,7 +203,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components hostBind.UnbindFrom(lastRoom.Host); statusBind.UnbindFrom(lastRoom.Status); typeBind.UnbindFrom(lastRoom.Type); - beatmapBind.UnbindFrom(lastRoom.Beatmap); + playlistBind.UnbindFrom(lastRoom.Playlist); maxParticipantsBind.UnbindFrom(lastRoom.MaxParticipants); participantsBind.UnbindFrom(lastRoom.Participants); } @@ -215,7 +214,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components hostBind.BindTo(newRoom.Host); statusBind.BindTo(newRoom.Status); typeBind.BindTo(newRoom.Type); - beatmapBind.BindTo(newRoom.Beatmap); + playlistBind.BindTo(newRoom.Playlist); maxParticipantsBind.BindTo(newRoom.MaxParticipants); participantsBind.BindTo(newRoom.Participants); @@ -239,6 +238,16 @@ namespace osu.Game.Screens.Multi.Lounge.Components lastRoom = newRoom; } + private void updatePlaylist() + { + // For now, only the first playlist item is supported + var item = playlistBind.First(); + + beatmap.Value = beatmaps.GetWorkingBeatmap(item.Beatmap); + background.Beatmap.Value = item.Beatmap; + beatmapTypeInfo.Beatmap.Value = item.Beatmap; + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 005378756e..4e3349056c 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Multi.Match.Components { public const float HEIGHT = 200; - public readonly IBindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); private readonly Box tabStrip; diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index e4eb2046b2..d6098674c1 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -6,7 +6,6 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -23,10 +22,10 @@ namespace osu.Game.Screens.Multi.Match.Components private const float field_padding = 45; private readonly Bindable nameBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); + private readonly IBindableCollection playlistBind = new BindableCollection(); private readonly Container content; @@ -160,7 +159,7 @@ namespace osu.Game.Screens.Multi.Match.Components typeLabel.Colour = colours.Yellow; nameBind.BindTo(room.Name); - beatmapBind.BindTo(room.Beatmap); + playlistBind.BindTo(room.Playlist); availabilityBind.BindTo(room.Availability); typeBind.BindTo(room.Type); maxParticipantsBind.BindTo(room.MaxParticipants); @@ -179,7 +178,7 @@ namespace osu.Game.Screens.Multi.Match.Components ApplyButton.Enabled.Value = hasValidSettings; } - private bool hasValidSettings => NameField.Text.Length > 0 && beatmapBind.Value != null; + private bool hasValidSettings => NameField.Text.Length > 0 && playlistBind.Count > 0; protected override void PopIn() { diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index a2a7c4e70d..b4ff73bbe4 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -2,6 +2,7 @@ // 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.Configuration; using osu.Framework.Graphics; @@ -20,12 +21,12 @@ namespace osu.Game.Screens.Multi.Match private readonly Participants participants; private readonly Bindable nameBind = new Bindable(); - private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); + private readonly BindableCollection playlistBind = new BindableCollection(); protected override Drawable TransitionContent => participants; @@ -33,6 +34,9 @@ namespace osu.Game.Screens.Multi.Match public override string ShortTitle => "room"; + private readonly Components.Header header; + private readonly Info info; + [Cached] private readonly Room room; @@ -47,16 +51,13 @@ namespace osu.Game.Screens.Multi.Match this.room = room; nameBind.BindTo(room.Name); - beatmapBind.BindTo(room.Beatmap); statusBind.BindTo(room.Status); availabilityBind.BindTo(room.Availability); typeBind.BindTo(room.Type); participantsBind.BindTo(room.Participants); maxParticipantsBind.BindTo(room.MaxParticipants); - Components.Header header; RoomSettingsOverlay settings; - Info info; Children = new Drawable[] { @@ -86,7 +87,6 @@ namespace osu.Game.Screens.Multi.Match }; header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect()); - header.Beatmap.BindTo(beatmapBind); header.Tabs.Current.ValueChanged += t => { @@ -96,7 +96,6 @@ namespace osu.Game.Screens.Multi.Match settings.Hide(); }; - info.Beatmap.BindTo(beatmapBind); info.Name.BindTo(nameBind); info.Status.BindTo(statusBind); info.Availability.BindTo(availabilityBind); @@ -104,14 +103,49 @@ namespace osu.Game.Screens.Multi.Match participants.Users.BindTo(participantsBind); participants.MaxParticipants.BindTo(maxParticipantsBind); + + playlistBind.ItemsAdded += _ => updatePlaylist(); + playlistBind.ItemsRemoved += _ => updatePlaylist(); } [BackgroundDependencyLoader] private void load() { - beatmapBind.BindTo(room.Beatmap); - beatmapBind.BindValueChanged(b => Beatmap.Value = beatmapManager.GetWorkingBeatmap(room.Beatmap.Value), true); - Beatmap.BindValueChanged(b => beatmapBind.Value = b.BeatmapInfo); + Beatmap.BindValueChanged(b => + { + playlistBind.Clear(); + + var newItem = new PlaylistItem + { + Beatmap = b.BeatmapInfo, + Ruleset = Ruleset.Value + }; + + newItem.RequiredMods.Clear(); + newItem.RequiredMods.AddRange(b.Mods.Value); + + playlistBind.Add(newItem); + }); + + playlistBind.BindTo(room.Playlist); + } + + private void updatePlaylist() + { + if (playlistBind.Count == 0) + return; + + // For now, only the first playlist item is supported + var item = playlistBind.First(); + + header.Beatmap.Value = item.Beatmap; + info.Beatmap.Value = item.Beatmap; + + if (Beatmap.Value?.BeatmapInfo != item.Beatmap) + { + Beatmap.Value = beatmapManager.GetWorkingBeatmap(item.Beatmap); + Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); + } } } } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index d6c5a12d33..fead90f9a2 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -69,9 +69,6 @@ namespace osu.Game.Screens.Multi pi.SetRulesets(rulesets); } - // Temporarily - r.Beatmap.Value = r.Playlist.FirstOrDefault()?.Beatmap; - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == r.RoomID.Value); if (existing == null) rooms.Add(r); From 8e6a85058b198e820e5fd2e4c5446a49583b0401 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 12:35:05 +0900 Subject: [PATCH 134/355] Fix playlist-related errors --- osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs | 3 +++ osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index c425f8ef0a..5cf11e5c98 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -244,6 +244,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void updatePlaylist() { + if (playlistBind.Count == 0) + return; + // For now, only the first playlist item is supported var item = playlistBind.First(); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 1a2ff4c3d8..818fd78f32 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -240,6 +240,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void updatePlaylist() { + if (playlistBind.Count == 0) + return; + // For now, only the first playlist item is supported var item = playlistBind.First(); From 2e767a529253a6c99ec3d1c6a2dc50b07da21689 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 13:38:13 +0900 Subject: [PATCH 135/355] Fix incorrect acronym --- osu.Game/Rulesets/Mods/IMod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index 4a95ce8111..49a3963496 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods /// /// The shortened name of this mod. /// - [JsonProperty] + [JsonProperty("acronym")] string Acronym { get; } } } From 56fd4b95cd9c69cb46f7e8277484e5fdf2559504 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 13:38:27 +0900 Subject: [PATCH 136/355] Fix mod/beatmap selection not always working --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 42 ++++++--------------- osu.Game/Screens/Select/MatchSongSelect.cs | 18 ++++++++- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index ca3f1eeb54..1d713dd0b1 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; using osu.Game.Screens.Play; @@ -40,9 +39,6 @@ namespace osu.Game.Screens.Multi.Match private readonly Components.Header header; private readonly Info info; - [Cached] - private readonly Bindable> mods = new Bindable>(Enumerable.Empty()); - [Cached] private readonly Room room; @@ -96,7 +92,7 @@ namespace osu.Game.Screens.Multi.Match }, }; - header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect()); + header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect { Selected = addPlaylistItem }); header.Tabs.Current.ValueChanged += t => { @@ -110,38 +106,27 @@ namespace osu.Game.Screens.Multi.Match info.Status.BindTo(statusBind); info.Availability.BindTo(availabilityBind); info.Type.BindTo(typeBind); - info.Mods.BindTo(mods); participants.Users.BindTo(participantsBind); participants.MaxParticipants.BindTo(maxParticipantsBind); - playlistBind.ItemsAdded += _ => updatePlaylist(); - playlistBind.ItemsRemoved += _ => updatePlaylist(); + playlistBind.ItemsAdded += _ => setFromPlaylist(); + playlistBind.ItemsRemoved += _ => setFromPlaylist(); } [BackgroundDependencyLoader] private void load() { - Beatmap.BindValueChanged(b => - { - playlistBind.Clear(); - - var newItem = new PlaylistItem - { - Beatmap = b.BeatmapInfo, - Ruleset = Ruleset.Value - }; - - newItem.RequiredMods.Clear(); - newItem.RequiredMods.AddRange(b.Mods.Value); - - playlistBind.Add(newItem); - }); - playlistBind.BindTo(room.Playlist); } - private void updatePlaylist() + private void addPlaylistItem(PlaylistItem item) + { + playlistBind.Clear(); + playlistBind.Add(item); + } + + private void setFromPlaylist() { if (playlistBind.Count == 0) return; @@ -151,12 +136,9 @@ namespace osu.Game.Screens.Multi.Match header.Beatmap.Value = item.Beatmap; info.Beatmap.Value = item.Beatmap; + info.Mods.Value = item.RequiredMods; - if (Beatmap.Value?.BeatmapInfo != item.Beatmap) - { - Beatmap.Value = beatmapManager.GetWorkingBeatmap(item.Beatmap); - Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); - } + Beatmap.Value = beatmapManager.GetWorkingBeatmap(item.Beatmap); } private void onStart() diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 94ac951159..10f29d929d 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -1,17 +1,33 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi; namespace osu.Game.Screens.Select { public class MatchSongSelect : SongSelect, IMultiplayerScreen { + public Action Selected; + public string ShortTitle => "song selection"; protected override bool OnStart() { - if (IsCurrentScreen) Exit(); + var item = new PlaylistItem + { + Beatmap = Beatmap.Value.BeatmapInfo, + Ruleset = Ruleset.Value, + }; + + item.RequiredMods.AddRange(SelectedMods.Value); + + Selected?.Invoke(item); + + if (IsCurrentScreen) + Exit(); + return true; } } From c9c04a6200bf51618d221de8b72f816edfb603e6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 13:43:52 +0900 Subject: [PATCH 137/355] Fix ToBeatmap not using the correct metadata Metadata is always come from the API via the beatmap set. --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index b96e4bedf6..2b4c69d332 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -59,15 +59,17 @@ namespace osu.Game.Online.API.Requests.Responses public BeatmapInfo ToBeatmap(RulesetStore rulesets) { + var set = BeatmapSet.ToBeatmapSet(rulesets); + return new BeatmapInfo { - Metadata = this, + Metadata = set.Metadata, Ruleset = rulesets.GetRuleset(ruleset), StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, Version = version, Status = Status, - BeatmapSet = BeatmapSet.ToBeatmapSet(rulesets), + BeatmapSet = set, BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, From b83f99d90a88e2b1754098ee87c30142a7cee391 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 14:20:03 +0900 Subject: [PATCH 138/355] Fix up header sizing + styling --- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 10 ++++ .../Screens/Multi/Match/Components/Header.cs | 2 +- .../Multi/Match/Components/HeaderButton.cs | 48 +++++++++++++++++++ .../Screens/Multi/Match/Components/Info.cs | 43 +++++++++-------- .../Multi/Match/Components/ReadyButton.cs | 41 ++-------------- .../Match/Components/ViewBeatmapButton.cs | 19 ++++++++ osu.Game/Screens/Multi/Match/MatchScreen.cs | 24 +++++----- 7 files changed, 120 insertions(+), 67 deletions(-) create mode 100644 osu.Game/Screens/Multi/Match/Components/HeaderButton.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 37b3f6030d..0272581a8f 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.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 System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -13,6 +15,14 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseMatchInfo : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Info), + typeof(HeaderButton), + typeof(ReadyButton), + typeof(ViewBeatmapButton) + }; + [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 4e3349056c..db71f7d2fe 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Multi.Match.Components tabStrip.Colour = colours.Yellow; } - private class BeatmapSelectButton : TriangleButton + private class BeatmapSelectButton : HeaderButton { private readonly IBindable roomIDBind = new Bindable(); diff --git a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs new file mode 100644 index 0000000000..30fe609ede --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class HeaderButton : TriangleButton + { + [BackgroundDependencyLoader] + private void load() + { + BackgroundColour = OsuColour.FromHex(@"1187aa"); + + Triangles.ColourLight = OsuColour.FromHex(@"277b9c"); + Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); + Triangles.TriangleScale = 1.5f; + + Add(new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = 1f, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.15f, + Blending = BlendingMode.Additive, + }, + }); + } + + protected override SpriteText CreateText() => new OsuSpriteText + { + Depth = -1, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Font = @"Exo2.0-Light", + TextSize = 30, + }; + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index f63fed8152..4912c95327 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -23,8 +23,6 @@ namespace osu.Game.Screens.Multi.Match.Components { public class Info : Container { - public const float HEIGHT = 156; - public Action OnStart; private readonly OsuSpriteText availabilityStatus; @@ -41,7 +39,7 @@ namespace osu.Game.Screens.Multi.Match.Components public Info() { RelativeSizeAxes = Axes.X; - Height = HEIGHT; + AutoSizeAxes = Axes.Y; BeatmapTypeInfo beatmapTypeInfo; OsuSpriteText name; @@ -56,14 +54,16 @@ namespace osu.Game.Screens.Multi.Match.Components }, new Container { - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, Children = new Drawable[] { - new Container + new FillFlowContainer { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), Padding = new MarginPadding { Vertical = 20 }, Children = new Drawable[] { @@ -75,12 +75,10 @@ namespace osu.Game.Screens.Multi.Match.Components { name = new OsuSpriteText { TextSize = 30 }, availabilityStatus = new OsuSpriteText { TextSize = 14 }, - }, + } }, new FillFlowContainer { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Children = new Drawable[] @@ -93,18 +91,25 @@ namespace osu.Game.Screens.Multi.Match.Components }, } } - }, }, - new ReadyButton + new FillFlowContainer { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - Size = new Vector2(200, 1), - Padding = new MarginPadding { Vertical = 10 }, - Action = () => OnStart?.Invoke() - }, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.X, + Height = 70, + Spacing = new Vector2(10, 0), + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new ViewBeatmapButton(), + new ReadyButton + { + Action = () => OnStart?.Invoke() + } + } + } }, }, }; diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index f0ca013b62..ec07b5ec09 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -1,50 +1,19 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; +using osuTK; namespace osu.Game.Screens.Multi.Match.Components { - public class ReadyButton : TriangleButton + public class ReadyButton : HeaderButton { - [BackgroundDependencyLoader] - private void load() + public ReadyButton() { - BackgroundColour = OsuColour.FromHex(@"1187aa"); - - Triangles.ColourLight = OsuColour.FromHex(@"277b9c"); - Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); - Triangles.TriangleScale = 1.5f; + RelativeSizeAxes = Axes.Y; + Size = new Vector2(200, 1); Text = "Start"; - - Add(new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 1f, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.15f, - Blending = BlendingMode.Additive, - }, - }); } - - protected override SpriteText CreateText() => new OsuSpriteText - { - Depth = -1, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Font = @"Exo2.0-Light", - TextSize = 30, - }; } } diff --git a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs new file mode 100644 index 0000000000..e9cff656c2 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osuTK; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class ViewBeatmapButton : HeaderButton + { + public ViewBeatmapButton() + { + RelativeSizeAxes = Axes.Y; + Size = new Vector2(200, 1); + + Text = "View beatmap"; + } + } +} diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 1d713dd0b1..82b234e9c8 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -66,19 +66,21 @@ namespace osu.Game.Screens.Multi.Match Children = new Drawable[] { - header = new Components.Header - { - Depth = -1, - }, - info = new Info - { - Margin = new MarginPadding { Top = Components.Header.HEIGHT }, - OnStart = onStart - }, - participants = new Participants + new GridContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Components.Header.HEIGHT + Info.HEIGHT }, + Content = new[] + { + new Drawable[] { header = new Components.Header { Depth = -1 } }, + new Drawable[] { info = new Info { OnStart = onStart } }, + new Drawable[] { participants = new Participants { RelativeSizeAxes = Axes.Both } }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed), + } }, new Container { From 3de65238a2b5a41a62bde845ca8a675dbe3a70eb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 14:33:50 +0900 Subject: [PATCH 139/355] Completely hide the select beatmap button for now --- osu.Game/Screens/Multi/Match/Components/Header.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index db71f7d2fe..4b831ed3c6 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -114,7 +113,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void load() { roomIDBind.BindTo(room.RoomID); - roomIDBind.BindValueChanged(v => Enabled.Value = !v.HasValue, true); + roomIDBind.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true); } } From 28192aef90103a6e80096aecb0b0534db331546d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 15:03:49 +0900 Subject: [PATCH 140/355] Fix nullref --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 2b4c69d332..7b42672c2e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -59,11 +59,11 @@ namespace osu.Game.Online.API.Requests.Responses public BeatmapInfo ToBeatmap(RulesetStore rulesets) { - var set = BeatmapSet.ToBeatmapSet(rulesets); + var set = BeatmapSet?.ToBeatmapSet(rulesets); return new BeatmapInfo { - Metadata = set.Metadata, + Metadata = set?.Metadata ?? this, Ruleset = rulesets.GetRuleset(ruleset), StarDifficulty = starDifficulty, OnlineBeatmapID = OnlineBeatmapID, From 83bf37a302395fa3cee5112afe3b628f88fd0f9c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 15:04:04 +0900 Subject: [PATCH 141/355] Enable/disable the view beatmap + ready buttons based on beatmap presence --- .../Screens/Multi/Match/Components/Info.cs | 9 +++- .../Multi/Match/Components/ReadyButton.cs | 41 +++++++++++++++++++ .../Match/Components/ViewBeatmapButton.cs | 27 ++++++++++++ osu.Game/Screens/Multi/Match/MatchScreen.cs | 1 + 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index 4912c95327..1750323486 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -41,6 +41,8 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + ReadyButton readyButton; + ViewBeatmapButton viewBeatmapButton; BeatmapTypeInfo beatmapTypeInfo; OsuSpriteText name; ModDisplay modDisplay; @@ -103,8 +105,8 @@ namespace osu.Game.Screens.Multi.Match.Components Direction = FillDirection.Horizontal, Children = new Drawable[] { - new ViewBeatmapButton(), - new ReadyButton + viewBeatmapButton = new ViewBeatmapButton(), + readyButton = new ReadyButton { Action = () => OnStart?.Invoke() } @@ -118,6 +120,9 @@ namespace osu.Game.Screens.Multi.Match.Components beatmapTypeInfo.Type.BindTo(Type); modDisplay.Current.BindTo(Mods); + viewBeatmapButton.Beatmap.BindTo(Beatmap); + readyButton.Beatmap.BindTo(Beatmap); + Availability.BindValueChanged(_ => updateAvailabilityStatus()); Status.BindValueChanged(_ => updateAvailabilityStatus()); Name.BindValueChanged(n => name.Text = n); diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index ec07b5ec09..c52a3be7cb 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -1,13 +1,22 @@ // 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.Configuration; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osuTK; namespace osu.Game.Screens.Multi.Match.Components { public class ReadyButton : HeaderButton { + public readonly IBindable Beatmap = new Bindable(); + + [Resolved] + private BeatmapManager beatmaps { get; set; } + public ReadyButton() { RelativeSizeAxes = Axes.Y; @@ -15,5 +24,37 @@ namespace osu.Game.Screens.Multi.Match.Components Text = "Start"; } + + [BackgroundDependencyLoader] + private void load() + { + beatmaps.ItemAdded += beatmapAdded; + + Beatmap.BindValueChanged(updateEnabledState, true); + } + + private void updateEnabledState(BeatmapInfo beatmap) + { + if (beatmap?.OnlineBeatmapID == null) + { + Enabled.Value = false; + return; + } + + Enabled.Value = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID) != null; + } + + private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) + { + if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID)) + Schedule(() => Enabled.Value = true); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + beatmaps.ItemAdded -= beatmapAdded; + } } } diff --git a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs index e9cff656c2..82d0761fbf 100644 --- a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs @@ -1,13 +1,21 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osuTK; namespace osu.Game.Screens.Multi.Match.Components { public class ViewBeatmapButton : HeaderButton { + public readonly IBindable Beatmap = new Bindable(); + + [Resolved(CanBeNull = true)] + private OsuGame osuGame { get; set; } + public ViewBeatmapButton() { RelativeSizeAxes = Axes.Y; @@ -15,5 +23,24 @@ namespace osu.Game.Screens.Multi.Match.Components Text = "View beatmap"; } + + [BackgroundDependencyLoader] + private void load() + { + if (osuGame != null) + Beatmap.BindValueChanged(updateAction, true); + } + + private void updateAction(BeatmapInfo beatmap) + { + if (beatmap == null) + { + Enabled.Value = false; + return; + } + + Action = () => osuGame.ShowBeatmap(beatmap.OnlineBeatmapID ?? 0); + Enabled.Value = true; + } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 82b234e9c8..dba9c8c14e 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -140,6 +140,7 @@ namespace osu.Game.Screens.Multi.Match info.Beatmap.Value = item.Beatmap; info.Mods.Value = item.RequiredMods; + // Todo: item.Beatmap can be null here... Beatmap.Value = beatmapManager.GetWorkingBeatmap(item.Beatmap); } From a6fc1280943dea4a38f1942b7234b65d31726238 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 15:41:05 +0900 Subject: [PATCH 142/355] Fix WaveOverlayContainer always being present --- osu.Game/Overlays/WaveOverlayContainer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index c5a4953c5e..5f7cf17a9d 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -25,13 +25,20 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); + Waves.Show(); + + this.FadeIn(); } protected override void PopOut() { base.PopOut(); + Waves.Hide(); + + // this is required or we will remain present even though our waves are hidden. + this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); } } } From 9072af9792a0133e72cdd2272cd2c92aefb91599 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 15:48:34 +0900 Subject: [PATCH 143/355] Move bulk of method into separate private method with minor clean-ups --- osu.Game/Online/API/APIAccess.cs | 78 +++++++++++++++----------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index cf709e2162..a1376b8b94 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -196,52 +196,13 @@ namespace osu.Game.Online.API /// true if we should remove this request from the queue. private bool handleRequest(APIRequest req) { - bool handleWebException(WebException we) - { - HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode - ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); - - // special cases for un-typed but useful message responses. - switch (we.Message) - { - case "Unauthorized": - case "Forbidden": - statusCode = HttpStatusCode.Unauthorized; - break; - } - - switch (statusCode) - { - case HttpStatusCode.Unauthorized: - Logout(false); - return true; - case HttpStatusCode.RequestTimeout: - failureCount++; - log.Add($@"API failure count is now {failureCount}"); - - if (failureCount < 3) - //we might try again at an api level. - return false; - - State = APIState.Failing; - flushQueue(); - return true; - } - - return true; - } - try { Logger.Log($@"Performing request {req}", LoggingTarget.Network); req.Failure += ex => { - switch (ex) - { - case WebException we: - handleWebException(we); - break; - } + if (ex is WebException we) + handleWebException(we); }; req.Perform(this); @@ -296,6 +257,41 @@ namespace osu.Game.Online.API } } + private bool handleWebException(WebException we) + { + HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode + ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); + + // special cases for un-typed but useful message responses. + switch (we.Message) + { + case "Unauthorized": + case "Forbidden": + statusCode = HttpStatusCode.Unauthorized; + break; + } + + switch (statusCode) + { + case HttpStatusCode.Unauthorized: + Logout(false); + return true; + case HttpStatusCode.RequestTimeout: + failureCount++; + log.Add($@"API failure count is now {failureCount}"); + + if (failureCount < 3) + //we might try again at an api level. + return false; + + State = APIState.Failing; + flushQueue(); + return true; + } + + return true; + } + public bool IsLoggedIn => LocalUser.Value.Id > 1; public void Queue(APIRequest request) From e3ad226075f96422f8bdb6989e9044a7bb0378d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 16:11:00 +0900 Subject: [PATCH 144/355] Use the local beatmap if existing, fixing player not loading objects --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index dba9c8c14e..00e63c11f3 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -141,7 +141,9 @@ namespace osu.Game.Screens.Multi.Match info.Mods.Value = item.RequiredMods; // Todo: item.Beatmap can be null here... - Beatmap.Value = beatmapManager.GetWorkingBeatmap(item.Beatmap); + var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; + + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); } private void onStart() From edefdb18f81eb5fb058191b527a9a85c311acb09 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 16:16:38 +0900 Subject: [PATCH 145/355] Fix beatmap not having any mods when going into play --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 00e63c11f3..5fcbc3a669 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -142,8 +142,8 @@ namespace osu.Game.Screens.Multi.Match // Todo: item.Beatmap can be null here... var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); + Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); } private void onStart() From 5f0069eb837a8300efc0f90c35cf1415a0fe4ade Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 17:35:05 +0900 Subject: [PATCH 146/355] Fix incorrect ruleset being sent to API --- osu.Game/Screens/Select/MatchSongSelect.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 10f29d929d..2008c9b783 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -19,6 +19,7 @@ namespace osu.Game.Screens.Select { Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = Ruleset.Value, + RulesetID = Ruleset.Value.ID ?? 0 }; item.RequiredMods.AddRange(SelectedMods.Value); From de0fc2a0deae3e509751e72777de33be8eeec1fa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 17:35:18 +0900 Subject: [PATCH 147/355] Fix beatmap + ruleset being changeable --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 16 ++++++++++++++-- osu.Game/Screens/Multi/Multiplayer.cs | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 5fcbc3a669..abcec16089 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -32,6 +32,9 @@ namespace osu.Game.Screens.Multi.Match protected override Drawable TransitionContent => participants; + public override bool AllowBeatmapRulesetChange => allowBeatmapRulesetChange; + private bool allowBeatmapRulesetChange; + public override string Title => room.Name.Value; public override string ShortTitle => "room"; @@ -140,10 +143,19 @@ namespace osu.Game.Screens.Multi.Match info.Beatmap.Value = item.Beatmap; info.Mods.Value = item.RequiredMods; + allowBeatmapRulesetChange = true; + // Todo: item.Beatmap can be null here... var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); + + Schedule(() => + { + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); + Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); + Ruleset.Value = item.Ruleset; + + allowBeatmapRulesetChange = false; + }); } private void onStart() diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 0150452677..0169d32c75 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -19,6 +19,10 @@ namespace osu.Game.Screens.Multi { private readonly MultiplayerWaveContainer waves; + public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; + + private OsuScreen currentScreen; + public Multiplayer() { Child = waves = new MultiplayerWaveContainer @@ -58,6 +62,8 @@ namespace osu.Game.Screens.Multi new Header(loungeScreen) }); + screenAdded(loungeScreen); + loungeScreen.Exited += s => Exit(); } @@ -96,6 +102,19 @@ namespace osu.Game.Screens.Multi base.LogoExiting(logo); } + private void screenAdded(Screen newScreen) + { + currentScreen = (OsuScreen)newScreen; + + newScreen.ModePushed += screenAdded; + newScreen.Exited += screenRemoved; + } + + private void screenRemoved(Screen newScreen) + { + currentScreen = (OsuScreen)newScreen; + } + private class MultiplayerWaveContainer : WaveContainer { protected override bool StartHidden => true; From 3fda40c4acae0ce25d8a96e18f9bc196c8f2d6d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 17:42:11 +0900 Subject: [PATCH 148/355] Ignore annoying tests for now --- osu.Game.Tests/Visual/TestCasePollingComponent.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/TestCasePollingComponent.cs index a77a4a7d57..b4b9d465e5 100644 --- a/osu.Game.Tests/Visual/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/TestCasePollingComponent.cs @@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual }; }); - //[Test] + [Test] public void TestInstantPolling() { createPoller(true); @@ -81,6 +81,7 @@ namespace osu.Game.Tests.Visual } [Test] + [Ignore("i have no idea how to fix the timing of this one")] public void TestSlowPolling() { createPoller(false); @@ -121,7 +122,7 @@ namespace osu.Game.Tests.Visual }; }); - protected override double TimePerAction => 500000; + protected override double TimePerAction => 500; public class TestPoller : PollingComponent { From 64626f62dbe9db8c265076404c1460eabc31165a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 19:02:25 +0900 Subject: [PATCH 149/355] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ed0e6c8417..305c9035b5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 38fd35a0cf450e30fa1845e938728c2424676613 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 19:17:21 +0900 Subject: [PATCH 150/355] Add polling time to ctor --- .idea/.idea.osu/.idea/runConfigurations/osu_.xml | 9 ++++++--- osu.Game/Online/PollingComponent.cs | 12 +++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu_.xml b/.idea/.idea.osu/.idea/runConfigurations/osu_.xml index 344301d4a7..2735f4ceb3 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/osu_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/osu_.xml @@ -1,17 +1,20 @@ - \ No newline at end of file diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index d9dcfc40c2..9d0bed7595 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -22,7 +22,8 @@ namespace osu.Game.Online private double timeBetweenPolls; /// - /// The time that should be waited between polls. + /// The time in milliseconds to wait between polls. + /// Setting to zero stops all polling. /// public double TimeBetweenPolls { @@ -35,6 +36,15 @@ namespace osu.Game.Online } } + /// + /// + /// + /// The initial time in milliseconds to wait between polls. Setting to zero stops al polling. + protected PollingComponent(double timeBetweenPolls = 0) + { + TimeBetweenPolls = timeBetweenPolls; + } + protected override void LoadComplete() { base.LoadComplete(); From d9fc7c7d66dd08532107c6fc18df7055105f1375 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 19:51:27 +0900 Subject: [PATCH 151/355] Separate out Leaderboard into BeatmapLeaderboard --- osu.Game.Tests/Visual/TestCaseLeaderboard.cs | 5 +- .../Online/API/Requests/GetScoresRequest.cs | 6 +- .../Leaderboards/DrawableRank.cs | 4 +- .../Leaderboards/Leaderboard.cs | 113 +++++------------- .../Leaderboards/LeaderboardScore.cs | 79 +++++++----- .../Leaderboards/MessagePlaceholder.cs | 2 +- .../Leaderboards/Placeholder.cs | 2 +- .../Leaderboards/PlaceholderState.cs | 2 +- .../RetrievalFailurePlaceholder.cs | 2 +- .../BeatmapSet/Scores/DrawableScore.cs | 2 +- .../BeatmapSet/Scores/DrawableTopScore.cs | 2 +- .../Sections/Ranks/DrawableProfileScore.cs | 2 +- .../Sections/Recent/DrawableRecentActivity.cs | 2 +- .../Screens/Ranking/ResultsPageRanking.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 2 +- osu.Game/Screens/Select/BeatmapDetailArea.cs | 6 +- .../Select/Leaderboards/BeatmapLeaderboard.cs | 87 ++++++++++++++ ...ardScope.cs => BeatmapLeaderboardScope.cs} | 2 +- .../Leaderboards/BeatmapLeaderboardScore.cs | 34 ++++++ 19 files changed, 224 insertions(+), 132 deletions(-) rename osu.Game/{Screens/Select => Online}/Leaderboards/DrawableRank.cs (96%) rename osu.Game/{Screens/Select => Online}/Leaderboards/Leaderboard.cs (76%) rename osu.Game/{Screens/Select => Online}/Leaderboards/LeaderboardScore.cs (87%) rename osu.Game/{Screens/Select => Online}/Leaderboards/MessagePlaceholder.cs (94%) rename osu.Game/{Screens/Select => Online}/Leaderboards/Placeholder.cs (94%) rename osu.Game/{Screens/Select => Online}/Leaderboards/PlaceholderState.cs (88%) rename osu.Game/{Screens/Select => Online}/Leaderboards/RetrievalFailurePlaceholder.cs (97%) create mode 100644 osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs rename osu.Game/Screens/Select/Leaderboards/{LeaderboardScope.cs => BeatmapLeaderboardScope.cs} (87%) create mode 100644 osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index f7630f0902..10d7eaee8a 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using osuTK; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Scoring; @@ -36,7 +37,7 @@ namespace osu.Game.Tests.Visual Origin = Anchor.Centre, Anchor = Anchor.Centre, Size = new Vector2(550f, 450f), - Scope = LeaderboardScope.Global, + Scope = BeatmapLeaderboardScope.Global, }); AddStep(@"New Scores", newScores); @@ -275,7 +276,7 @@ namespace osu.Game.Tests.Visual }; } - private class FailableLeaderboard : Leaderboard + private class FailableLeaderboard : BeatmapLeaderboard { public void SetRetrievalState(PlaceholderState state) { diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 2751dd956b..ae2c7dc269 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -13,15 +13,15 @@ namespace osu.Game.Online.API.Requests public class GetScoresRequest : APIRequest { private readonly BeatmapInfo beatmap; - private readonly LeaderboardScope scope; + private readonly BeatmapLeaderboardScope scope; private readonly RulesetInfo ruleset; - public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, LeaderboardScope scope = LeaderboardScope.Global) + public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global) { if (!beatmap.OnlineBeatmapID.HasValue) throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}."); - if (scope == LeaderboardScope.Local) + if (scope == BeatmapLeaderboardScope.Local) throw new InvalidOperationException("Should not attempt to request online scores for a local scoped leaderboard"); this.beatmap = beatmap; diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs similarity index 96% rename from osu.Game/Screens/Select/Leaderboards/DrawableRank.cs rename to osu.Game/Online/Leaderboards/DrawableRank.cs index 3258a62adf..1c68c64180 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -2,14 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Extensions; using osu.Game.Scoring; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public class DrawableRank : Container { diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs similarity index 76% rename from osu.Game/Screens/Select/Leaderboards/Leaderboard.cs rename to osu.Game/Online/Leaderboards/Leaderboard.cs index a65cc6f096..8e83c8ad5a 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -3,38 +3,30 @@ using System; using System.Collections.Generic; -using osuTK; -using osuTK.Graphics; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; -using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; 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; +using osu.Game.Screens.Select.Leaderboards; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { - public class Leaderboard : Container + public abstract class Leaderboard : Container { private const double fade_duration = 300; private readonly ScrollContainer scrollContainer; private readonly Container placeholderContainer; - private FillFlowContainer scrollFlow; - - private readonly IBindable ruleset = new Bindable(); - - public Action ScoreSelected; + private FillFlowContainer> scrollFlow; private readonly LoadingAnimation loading; @@ -42,9 +34,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 @@ -64,13 +56,13 @@ namespace osu.Game.Screens.Select.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - var flow = scrollFlow = new FillFlowContainer + var flow = scrollFlow = new FillFlowContainer> { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 5f), Padding = new MarginPadding { Top = 10, Bottom = 5 }, - ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) }) + ChildrenEnumerable = scores.Select((s, index) => CreateScoreVisualiser(s, index + 1)) }; // schedule because we may not be loaded yet (LoadComponentAsync complains). @@ -96,18 +88,18 @@ namespace osu.Game.Screens.Select.Leaderboards } } - private LeaderboardScope scope; + private TScope scope; - public LeaderboardScope Scope + public TScope Scope { get { return scope; } set { - if (value == scope) + if (value.Equals(scope)) return; scope = value; - updateScores(); + UpdateScores(); } } @@ -137,7 +129,7 @@ namespace osu.Game.Screens.Select.Leaderboards case PlaceholderState.NetworkFailure: replacePlaceholder(new RetrievalFailurePlaceholder { - OnRetry = updateScores, + OnRetry = UpdateScores, }); break; case PlaceholderState.Unavailable: @@ -159,7 +151,7 @@ namespace osu.Game.Screens.Select.Leaderboards } } - public Leaderboard() + protected Leaderboard() { Children = new Drawable[] { @@ -177,36 +169,14 @@ namespace osu.Game.Screens.Select.Leaderboards } private APIAccess api; - private BeatmapInfo beatmap; - - [Resolved] - private ScoreManager scoreManager { get; set; } private ScheduledDelegate pendingUpdateScores; - public BeatmapInfo Beatmap - { - get { return beatmap; } - set - { - if (beatmap == value) - return; - - beatmap = value; - Scores = null; - - updateScores(); - } - } - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, IBindable parentRuleset) + [BackgroundDependencyLoader(true)] + private void load(APIAccess api) { this.api = api; - ruleset.BindTo(parentRuleset); - ruleset.ValueChanged += _ => updateScores(); - if (api != null) api.OnStateChange += handleApiStateChange; } @@ -219,21 +189,17 @@ namespace osu.Game.Screens.Select.Leaderboards api.OnStateChange -= handleApiStateChange; } - public void RefreshScores() => updateScores(); + public void RefreshScores() => UpdateScores(); - private GetScoresRequest getScoresRequest; + private APIRequest getScoresRequest; private void handleApiStateChange(APIState oldState, APIState newState) { - if (Scope == LeaderboardScope.Local) - // No need to respond to API state change while current scope is local - return; - if (newState == APIState.Online) - updateScores(); + UpdateScores(); } - private void updateScores() + protected void UpdateScores() { // don't display any scores or placeholder until the first Scores_Set has been called. // this avoids scope changes flickering a "no scores" placeholder before initialisation of song select is finished. @@ -245,40 +211,23 @@ namespace osu.Game.Screens.Select.Leaderboards pendingUpdateScores?.Cancel(); pendingUpdateScores = Schedule(() => { - if (Scope == LeaderboardScope.Local) - { - Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray(); - PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; - return; - } - - if (Beatmap?.OnlineBeatmapID == null) - { - PlaceholderState = PlaceholderState.Unavailable; - return; - } - if (api?.IsLoggedIn != true) { PlaceholderState = PlaceholderState.NotLoggedIn; return; } - if (Scope != LeaderboardScope.Global && !api.LocalUser.Value.IsSupporter) - { - PlaceholderState = PlaceholderState.NotSupporter; - return; - } - PlaceholderState = PlaceholderState.Retrieving; loading.Show(); - getScoresRequest = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope); - getScoresRequest.Success += r => Schedule(() => + getScoresRequest = FetchScores(scores => Schedule(() => { - Scores = r.Scores; + Scores = scores; PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; - }); + })); + + if (getScoresRequest == null) + return; getScoresRequest.Failure += e => Schedule(() => { @@ -292,6 +241,8 @@ namespace osu.Game.Screens.Select.Leaderboards }); } + protected abstract APIRequest FetchScores(Action> scoresCallback); + private Placeholder currentPlaceholder; private void replacePlaceholder(Placeholder placeholder) @@ -344,5 +295,7 @@ namespace osu.Game.Screens.Select.Leaderboards } } } + + protected abstract LeaderboardScore CreateScoreVisualiser(TScoreModel model, int index); } } diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs similarity index 87% rename from osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs rename to osu.Game/Online/Leaderboards/LeaderboardScore.cs index 1ba529c0bf..63352754a8 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -1,9 +1,8 @@ // 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 osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -14,47 +13,60 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { - public class LeaderboardScore : OsuClickableContainer + public static class LeaderboardScore { - public static readonly float HEIGHT = 60; + public const float HEIGHT = 60; + } + public abstract class LeaderboardScore : OsuClickableContainer + { public readonly int RankPosition; - public readonly ScoreInfo Score; private const float corner_radius = 5; private const float edge_margin = 5; private const float background_alpha = 0.25f; private const float rank_width = 30; + protected Container RankContainer { get; private set; } + + private readonly TScoreModel score; + private Box background; private Container content; private Drawable avatar; - private DrawableRank scoreRank; + private Drawable scoreRank; private OsuSpriteText nameLabel; private GlowingSpriteText scoreLabel; - private ScoreComponentLabel maxCombo; - private ScoreComponentLabel accuracy; private Container flagBadgeContainer; private FillFlowContainer modsContainer; - public LeaderboardScore(ScoreInfo score, int rank) + private List statisticsLabels; + + protected LeaderboardScore(TScoreModel score, int rank) { - Score = score; + this.score = score; RankPosition = rank; RelativeSizeAxes = Axes.X; - Height = HEIGHT; + Height = LeaderboardScore.HEIGHT; } [BackgroundDependencyLoader] private void load() { + var user = GetUser(score); + + statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s.icon, s.value, s.name)).ToList(); + Children = new Drawable[] { new Container @@ -102,7 +114,7 @@ namespace osu.Game.Screens.Select.Leaderboards Children = new[] { avatar = new DelayedLoadWrapper( - new Avatar(Score.User) + new Avatar(user) { RelativeSizeAxes = Axes.Both, CornerRadius = corner_radius, @@ -117,18 +129,18 @@ namespace osu.Game.Screens.Select.Leaderboards }) { RelativeSizeAxes = Axes.None, - Size = new Vector2(HEIGHT - edge_margin * 2, HEIGHT - edge_margin * 2), + Size = new Vector2(LeaderboardScore.HEIGHT - edge_margin * 2, LeaderboardScore.HEIGHT - edge_margin * 2), }, new Container { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, - Position = new Vector2(HEIGHT - edge_margin, 0f), + Position = new Vector2(LeaderboardScore.HEIGHT - edge_margin, 0f), Children = new Drawable[] { nameLabel = new OsuSpriteText { - Text = Score.User.Username, + Text = user.Username, Font = @"Exo2.0-BoldItalic", TextSize = 23, }, @@ -149,7 +161,7 @@ namespace osu.Game.Screens.Select.Leaderboards Masking = true, Children = new Drawable[] { - new DrawableFlag(Score.User?.Country) + new DrawableFlag(user.Country) { Width = 30, RelativeSizeAxes = Axes.Y, @@ -164,11 +176,7 @@ namespace osu.Game.Screens.Select.Leaderboards Direction = FillDirection.Horizontal, Spacing = new Vector2(10f, 0f), 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"), - }, + Children = statisticsLabels }, }, }, @@ -183,17 +191,17 @@ 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")), - new Container + scoreLabel = new GlowingSpriteText(GetTotalScore(score).ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + RankContainer = new Container { Size = new Vector2(40f, 20f), Children = new[] { - scoreRank = new DrawableRank(Score.Rank) + scoreRank = new DrawableRank(GetRank(score)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(40f), + Size = new Vector2(40f) }, }, }, @@ -205,7 +213,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 = GetMods(score).Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, }, @@ -216,7 +224,7 @@ namespace osu.Game.Screens.Select.Leaderboards public override void Show() { - foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, maxCombo, accuracy, modsContainer }) + foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, modsContainer }.Concat(statisticsLabels)) d.FadeOut(); Alpha = 0; @@ -243,7 +251,7 @@ namespace osu.Game.Screens.Select.Leaderboards using (BeginDelayedSequence(50, true)) { - var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, }; + var drawables = new Drawable[] { flagBadgeContainer, modsContainer }.Concat(statisticsLabels).ToArray(); for (int i = 0; i < drawables.Length; i++) drawables[i].FadeIn(100 + i * 50); } @@ -263,6 +271,16 @@ namespace osu.Game.Screens.Select.Leaderboards base.OnHoverLost(e); } + protected abstract User GetUser(TScoreModel model); + + protected abstract IEnumerable GetMods(TScoreModel model); + + protected abstract IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(TScoreModel model); + + protected abstract int GetTotalScore(TScoreModel model); + + protected abstract ScoreRank GetRank(TScoreModel model); + private class GlowingSpriteText : Container { public GlowingSpriteText(string text, string font, int textSize, Color4 textColour, Color4 glowColour) @@ -324,8 +342,7 @@ namespace osu.Game.Screens.Select.Leaderboards public ScoreComponentLabel(FontAwesome icon, string value, string name) { this.name = name; - AutoSizeAxes = Axes.Y; - Width = 60; + AutoSizeAxes = Axes.Both; Child = content = new FillFlowContainer { diff --git a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs similarity index 94% rename from osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs rename to osu.Game/Online/Leaderboards/MessagePlaceholder.cs index f01a55b662..ea92836e6e 100644 --- a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public class MessagePlaceholder : Placeholder { diff --git a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs b/osu.Game/Online/Leaderboards/Placeholder.cs similarity index 94% rename from osu.Game/Screens/Select/Leaderboards/Placeholder.cs rename to osu.Game/Online/Leaderboards/Placeholder.cs index 468b43e54f..4994ce0e99 100644 --- a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs +++ b/osu.Game/Online/Leaderboards/Placeholder.cs @@ -5,7 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public abstract class Placeholder : OsuTextFlowContainer, IEquatable { diff --git a/osu.Game/Screens/Select/Leaderboards/PlaceholderState.cs b/osu.Game/Online/Leaderboards/PlaceholderState.cs similarity index 88% rename from osu.Game/Screens/Select/Leaderboards/PlaceholderState.cs rename to osu.Game/Online/Leaderboards/PlaceholderState.cs index 33a56540f3..504b03432f 100644 --- a/osu.Game/Screens/Select/Leaderboards/PlaceholderState.cs +++ b/osu.Game/Online/Leaderboards/PlaceholderState.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 -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public enum PlaceholderState { diff --git a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs similarity index 97% rename from osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs rename to osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs index 66a7793f7c..7fed40ed1a 100644 --- a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osuTK; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public class RetrievalFailurePlaceholder : Placeholder { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index f643e130aa..89416c1098 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -10,11 +10,11 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; 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.Screens.Select.Leaderboards; using osu.Game.Users; namespace osu.Game.Overlays.BeatmapSet.Scores diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 643839fa88..6259d85bee 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -12,12 +12,12 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; 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; namespace osu.Game.Overlays.BeatmapSet.Scores diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 1c39cb309c..18aa684664 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -6,8 +6,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Select.Leaderboards; using osu.Game.Rulesets.UI; using osu.Game.Scoring; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index fefb289d17..8b4fb1a229 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -10,7 +10,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; -using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Online.Leaderboards; namespace osu.Game.Overlays.Profile.Sections.Recent { diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index c5a5cc6ad9..3a75daaf60 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Ranking Colour = colours.GrayE, RelativeSizeAxes = Axes.Both, }, - new Leaderboard + new BeatmapLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 62103314e1..0774a63e98 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -19,11 +19,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; -using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions; using osu.Framework.Localisation; +using osu.Game.Online.Leaderboards; using osu.Game.Scoring; namespace osu.Game.Screens.Ranking diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index a6fbd201d0..c5c4960ed4 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select protected override Container Content => content; public readonly BeatmapDetails Details; - public readonly Leaderboard Leaderboard; + public readonly BeatmapLeaderboard Leaderboard; private WorkingBeatmap beatmap; public WorkingBeatmap Beatmap @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Select default: Details.Hide(); - Leaderboard.Scope = (LeaderboardScope)tab - 1; + Leaderboard.Scope = (BeatmapLeaderboardScope)tab - 1; Leaderboard.Show(); break; } @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select Alpha = 0, Margin = new MarginPadding { Top = details_padding }, }, - Leaderboard = new Leaderboard + Leaderboard = new BeatmapLeaderboard { RelativeSizeAxes = Axes.Both, } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs new file mode 100644 index 0000000000..b0cfad314c --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -0,0 +1,87 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets; +using osu.Game.Scoring; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public class BeatmapLeaderboard : Leaderboard + { + public Action ScoreSelected; + + private BeatmapInfo beatmap; + + public BeatmapInfo Beatmap + { + get { return beatmap; } + set + { + if (beatmap == value) + return; + + beatmap = value; + Scores = null; + + UpdateScores(); + } + } + + [Resolved] + private ScoreManager scoreManager { get; set; } + + [Resolved] + private IBindable ruleset { get; set; } + + [Resolved] + private APIAccess api { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + ruleset.ValueChanged += _ => UpdateScores(); + } + + protected override APIRequest FetchScores(Action> scoresCallback) + { + if (Scope == BeatmapLeaderboardScope.Local) + { + Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray(); + PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; + return null; + } + + if (Beatmap?.OnlineBeatmapID == null) + { + PlaceholderState = PlaceholderState.Unavailable; + return null; + } + + if (Scope != BeatmapLeaderboardScope.Global && !api.LocalUser.Value.IsSupporter) + { + PlaceholderState = PlaceholderState.NotSupporter; + return null; + } + + var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope); + + req.Success += r => scoresCallback?.Invoke(r.Scores); + + return req; + } + + protected override LeaderboardScore CreateScoreVisualiser(ScoreInfo model, int index) => new BeatmapLeaderboardScore(model, index) + { + Action = () => ScoreSelected?.Invoke(model) + }; + } +} diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs similarity index 87% rename from osu.Game/Screens/Select/Leaderboards/LeaderboardScope.cs rename to osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index 761f53a5e8..39d9580792 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs @@ -3,7 +3,7 @@ namespace osu.Game.Screens.Select.Leaderboards { - public enum LeaderboardScope + public enum BeatmapLeaderboardScope { Local, Country, diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs new file mode 100644 index 0000000000..098fff4052 --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.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 osu.Game.Graphics; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public class BeatmapLeaderboardScore : LeaderboardScore + { + public BeatmapLeaderboardScore(ScoreInfo score, int rank) + : base(score, rank) + { + } + + protected override User GetUser(ScoreInfo model) => model.User; + + protected override IEnumerable GetMods(ScoreInfo model) => model.Mods; + + protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(ScoreInfo model) => new[] + { + (FontAwesome.fa_link, model.MaxCombo.ToString(), "Max Combo"), + (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy") + }; + + protected override int GetTotalScore(ScoreInfo model) => model.TotalScore; + + protected override ScoreRank GetRank(ScoreInfo model) => model.Rank; + } +} From 13cabac386653da27ad6a4105847572792bf78fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 19:56:21 +0900 Subject: [PATCH 152/355] Update in line with framework changes --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 3d9a74ea2b..bfc437f763 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -9,7 +9,6 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Framework.Screens; using osu.Game.Graphics; @@ -35,7 +34,7 @@ namespace osu.Game.Overlays.AccountCreation private APIAccess api; private ShakeContainer registerShake; - private IEnumerable characterCheckText; + private IEnumerable characterCheckText; private OsuTextBox[] textboxes; private ProcessingOverlay processingOverlay; From 0b5f3c00bf2fdac0c6e833155a917dc56251a38e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Dec 2018 20:50:27 +0900 Subject: [PATCH 153/355] Revert "Fix WaveOverlayContainer always being present" This reverts commit a6fc1280943dea4a38f1942b7234b65d31726238. --- osu.Game/Overlays/WaveOverlayContainer.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 5f7cf17a9d..c5a4953c5e 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -25,20 +25,13 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); - Waves.Show(); - - this.FadeIn(); } protected override void PopOut() { base.PopOut(); - Waves.Hide(); - - // this is required or we will remain present even though our waves are hidden. - this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); } } } From e8007ac37fe9f90b23bb369cf11a226c4a0a2d1a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 19:52:03 +0900 Subject: [PATCH 154/355] Implement multiplayer room leaderboard --- .../Visual/TestCaseMatchLeaderboard.cs | 68 ++++++++++ osu.Game/Online/Leaderboards/Leaderboard.cs | 1 - .../Match/Components/MatchLeaderboard.cs | 119 ++++++++++++++++++ osu.Game/Screens/Multi/Match/MatchScreen.cs | 21 +++- 4 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs new file mode 100644 index 0000000000..cf475de1f0 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs @@ -0,0 +1,68 @@ +// 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 Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMatchLeaderboard : OsuTestCase + { + public TestCaseMatchLeaderboard() + { + Add(new MatchLeaderboard(new Room { RoomID = { Value = 3 } }) + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(550f, 450f), + Scope = MatchLeaderboardScope.Overall, + }); + } + + [Resolved] + private APIAccess api { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + var req = new GetRoomScoresRequest(); + req.Success += v => { }; + req.Failure += _ => { }; + + api.Queue(req); + } + + private class GetRoomScoresRequest : APIRequest> + { + protected override string Target => "rooms/3/leaderboard"; + } + + private class RoomScore + { + [JsonProperty("user")] + public User User { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty("total_score")] + public int TotalScore { get; set; } + + [JsonProperty("pp")] + public double PP { get; set; } + + [JsonProperty("attempts")] + public int TotalAttempts { get; set; } + + [JsonProperty("completed")] + public int CompletedAttempts { get; set; } + } + } +} diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 8e83c8ad5a..83cc289bc1 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -13,7 +13,6 @@ using osu.Framework.Threading; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; -using osu.Game.Screens.Select.Leaderboards; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs new file mode 100644 index 0000000000..ef1021bac6 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -0,0 +1,119 @@ +// 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 Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Leaderboards; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class MatchLeaderboard : Leaderboard + { + private readonly Room room; + + public MatchLeaderboard(Room room) + { + this.room = room; + } + + [BackgroundDependencyLoader] + private void load() + { + room.RoomID.BindValueChanged(_ => + { + Scores = null; + UpdateScores(); + }, true); + } + + protected override APIRequest FetchScores(Action> scoresCallback) + { + if (room.RoomID == null) + return null; + + var req = new GetRoomScoresRequest(room.RoomID.Value ?? 0); + + req.Success += r => scoresCallback?.Invoke(r); + + return req; + } + + protected override LeaderboardScore CreateScoreVisualiser(RoomScore model, int index) => new MatchLeaderboardScore(model, index); + + private class GetRoomScoresRequest : APIRequest> + { + private readonly int roomId; + + public GetRoomScoresRequest(int roomId) + { + this.roomId = roomId; + } + + protected override string Target => $@"rooms/{roomId}/leaderboard"; + } + } + + public class MatchLeaderboardScore : LeaderboardScore + { + public MatchLeaderboardScore(RoomScore score, int rank) + : base(score, rank) + { + } + + [BackgroundDependencyLoader] + private void load() + { + RankContainer.Alpha = 0; + } + + protected override User GetUser(RoomScore model) => model.User; + + protected override IEnumerable GetMods(RoomScore model) => Enumerable.Empty(); // Not implemented yet + + protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(RoomScore model) => new[] + { + (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy"), + (FontAwesome.fa_refresh, model.TotalAttempts.ToString(), "Total Attempts"), + (FontAwesome.fa_check, model.CompletedAttempts.ToString(), "Completed Beatmaps"), + }; + + protected override int GetTotalScore(RoomScore model) => model.TotalScore; + + protected override ScoreRank GetRank(RoomScore model) => ScoreRank.S; + } + + public enum MatchLeaderboardScope + { + Overall + } + + public class RoomScore + { + [JsonProperty("user")] + public User User { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty("total_score")] + public int TotalScore { get; set; } + + [JsonProperty("pp")] + public double PP { get; set; } + + [JsonProperty("attempts")] + public int TotalAttempts { get; set; } + + [JsonProperty("completed")] + public int CompletedAttempts { get; set; } + } +} diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index abcec16089..d4e73308c3 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -76,7 +76,26 @@ namespace osu.Game.Screens.Multi.Match { new Drawable[] { header = new Components.Header { Depth = -1 } }, new Drawable[] { info = new Info { OnStart = onStart } }, - new Drawable[] { participants = new Participants { RelativeSizeAxes = Axes.Both } }, + new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + participants = new Participants { RelativeSizeAxes = Axes.Both }, + new MatchLeaderboard(room) { RelativeSizeAxes = Axes.Both } + }, + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.Relative, 0.5f), + } + } + }, }, RowDimensions = new[] { From 9726eea0d02c07029e4cbc7324bd57043630e99a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 21:09:17 +0900 Subject: [PATCH 155/355] Basic score submission implementation --- osu.Game/Online/Multiplayer/Room.cs | 5 +- osu.Game/Scoring/ScoreInfo.cs | 25 ++++- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- .../Screens/Multi/Play/TimeshiftPlayer.cs | 97 +++++++++++++++++++ 4 files changed, 125 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 5e9fc4f008..5c24827d44 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -64,6 +64,9 @@ namespace osu.Game.Online.Multiplayer public class PlaylistItem { + [JsonProperty("id")] + public int ID { get; set; } + [JsonProperty("beatmap")] private APIBeatmap beatmap { get; set; } @@ -73,7 +76,7 @@ namespace osu.Game.Online.Multiplayer public BeatmapInfo Beatmap { get; set; } [JsonProperty("beatmap_id")] - public int BeatmapID => 847296; //Beatmap.OnlineBeatmapID ?? 0; + public int BeatmapID => Beatmap.OnlineBeatmapID ?? 0; [JsonProperty("ruleset_id")] public int RulesetID { get; set; } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index fb894e621e..a689590819 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -19,25 +19,38 @@ namespace osu.Game.Scoring { public int ID { get; set; } + [JsonProperty("rank")] public ScoreRank Rank { get; set; } + [JsonProperty("total_score")] public int TotalScore { get; set; } + [JsonProperty("accuracy")] [Column(TypeName="DECIMAL(1,4)")] public double Accuracy { get; set; } + [JsonIgnore] public double? PP { get; set; } + [JsonProperty("max_combo")] public int MaxCombo { get; set; } - public int Combo { get; set; } + [JsonIgnore] + public int Combo { get; set; } // Todo: Shouldn't exist in here + [JsonIgnore] public int RulesetID { get; set; } + [JsonProperty("passed")] + [NotMapped] + public bool Passed { get; set; } = true; + + [JsonIgnore] public virtual RulesetInfo Ruleset { get; set; } private Mod[] mods; + [JsonProperty("mods")] [NotMapped] public Mod[] Mods { @@ -62,6 +75,7 @@ namespace osu.Game.Scoring private string modsJson; + [JsonIgnore] [Column("Mods")] public string ModsJson { @@ -87,6 +101,7 @@ namespace osu.Game.Scoring [JsonIgnore] public User User; + [JsonIgnore] [Column("User")] public string UserString { @@ -97,15 +112,19 @@ namespace osu.Game.Scoring [JsonIgnore] public int BeatmapInfoID { get; set; } + [JsonIgnore] public virtual BeatmapInfo Beatmap { get; set; } + [JsonIgnore] public long? OnlineScoreID { get; set; } + [JsonIgnore] public DateTimeOffset Date { get; set; } - [JsonIgnore] + [JsonProperty("statistics")] public Dictionary Statistics = new Dictionary(); + [JsonIgnore] [Column("Statistics")] public string StatisticsJson { @@ -125,8 +144,10 @@ namespace osu.Game.Scoring [JsonIgnore] public List Files { get; set; } + [JsonIgnore] public string Hash { get; set; } + [JsonIgnore] public bool DeletePending { get; set; } [Serializable] diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index d4e73308c3..e4e8f8e305 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -183,7 +183,7 @@ namespace osu.Game.Screens.Multi.Match { default: case GameTypeTimeshift _: - multiplayer.Push(new PlayerLoader(new TimeshiftPlayer())); + multiplayer.Push(new PlayerLoader(new TimeshiftPlayer(room.RoomID.Value ?? 0, room.Playlist.First().ID))); break; } } diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 114d90dc79..5a9fab6aaf 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -1,11 +1,108 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Net.Http; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Framework.IO.Network; +using osu.Game.Online.API; +using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Screens.Multi.Play { public class TimeshiftPlayer : Player { + private readonly int roomId; + private readonly int playlistItemId; + + [Resolved] + private APIAccess api { get; set; } + + public TimeshiftPlayer(int roomId, int playlistItemId) + { + this.roomId = roomId; + this.playlistItemId = playlistItemId; + } + + private int token; + + [BackgroundDependencyLoader] + private void load() + { + var req = new CreateScoreRequest(roomId, playlistItemId); + req.Success += r => token = r.ID; + req.Failure += e => { }; + api.Queue(req); + } + + protected override ScoreInfo CreateScore() + { + var score = base.CreateScore(); + + var request = new SubmitScoreRequest(token, roomId, playlistItemId, score); + request.Success += () => { }; + request.Failure += e => { }; + api.Queue(request); + + return score; + } + } + + public class SubmitScoreRequest : APIRequest + { + private readonly int scoreId; + private readonly int roomId; + private readonly int playlistItemId; + private readonly ScoreInfo scoreInfo; + + public SubmitScoreRequest(int scoreId, int roomId, int playlistItemId, ScoreInfo scoreInfo) + { + this.scoreId = scoreId; + this.roomId = roomId; + this.playlistItemId = playlistItemId; + this.scoreInfo = scoreInfo; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.ContentType = "application/json"; + req.Method = HttpMethod.Put; + + req.AddRaw(JsonConvert.SerializeObject(scoreInfo)); + + return req; + } + + protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores/{scoreId}"; + } + + public class CreateScoreRequest : APIRequest + { + private readonly int roomId; + private readonly int playlistItemId; + + public CreateScoreRequest(int roomId, int playlistItemId) + { + this.roomId = roomId; + this.playlistItemId = playlistItemId; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Post; + return req; + } + + protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores"; + } + + public class CreateScoreResult + { + [JsonProperty("id")] + public int ID { get; set; } } } From 983a45c4d8cbdf2e1a92e70789dfa044005d67c3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 21:21:02 +0900 Subject: [PATCH 156/355] Fix invalid value --- osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index ef1021bac6..9d4ad3cb22 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Multi.Match.Components public int TotalScore { get; set; } [JsonProperty("pp")] - public double PP { get; set; } + public double? PP { get; set; } [JsonProperty("attempts")] public int TotalAttempts { get; set; } From 3892454eccfd936dcb8de103b2d21167a881ce0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Dec 2018 16:34:48 +0900 Subject: [PATCH 157/355] Improve the way text search works at song select --- .../Screens/Select/Carousel/CarouselBeatmap.cs | 6 +++--- osu.Game/Screens/Select/FilterCriteria.cs | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 272332f1ce..0f548bb667 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -26,10 +26,10 @@ namespace osu.Game.Screens.Select.Carousel bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps; - if (!string.IsNullOrEmpty(criteria.SearchText)) + foreach (var criteriaTerm in criteria.SearchTerms) match &= - Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteria.SearchText, StringComparison.InvariantCultureIgnoreCase) >= 0) || - Beatmap.Version.IndexOf(criteria.SearchText, StringComparison.InvariantCultureIgnoreCase) >= 0; + Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || + Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; Filtered.Value = !match; } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index bea806f00f..71cfedfdbf 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.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 System; +using System.Linq; using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; @@ -10,8 +12,22 @@ namespace osu.Game.Screens.Select { public GroupMode Group; public SortMode Sort; - public string SearchText; + + public string[] SearchTerms = Array.Empty(); + public RulesetInfo Ruleset; public bool AllowConvertedBeatmaps; + + private string searchText; + + public string SearchText + { + get { return searchText; } + set + { + searchText = value; + SearchTerms = searchText.Split(',', ' ', '!').Where(s => !string.IsNullOrEmpty(s)).ToArray(); + } + } } } From eec5afa3828ac70ea639b39030f431d156e25eb4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Dec 2018 16:37:37 +0900 Subject: [PATCH 158/355] Change inspection and add redundant parenthesis to appease codefactor --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.sln.DotSettings | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 0f548bb667..49779f5e11 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); - bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps; + bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); foreach (var criteriaTerm in criteria.SearchTerms) match &= diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index d6882282e6..112efb37f0 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -8,7 +8,8 @@ SOLUTION HINT WARNING - WARNING + + True WARNING WARNING HINT From 2fd2425cc40791f7f6e75f6bb4dc3e721acab35b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Dec 2018 11:04:38 +0900 Subject: [PATCH 159/355] Fix playlist deserialisation for creating rooms --- osu.Game/Online/Multiplayer/Room.cs | 65 +++++++++++++++------------ osu.Game/Screens/Multi/RoomManager.cs | 14 +++--- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 5c24827d44..0317b3c3e8 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -59,6 +59,9 @@ namespace osu.Game.Online.Multiplayer Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); + + Playlist.Clear(); + Playlist.AddRange(other.Playlist); } } @@ -68,15 +71,25 @@ namespace osu.Game.Online.Multiplayer public int ID { get; set; } [JsonProperty("beatmap")] - private APIBeatmap beatmap { get; set; } + private APIBeatmap apiBeatmap { get; set; } - public bool ShouldSerializebeatmap() => false; + public bool ShouldSerializeapiBeatmap() => false; + + private BeatmapInfo beatmap; [JsonIgnore] - public BeatmapInfo Beatmap { get; set; } + public BeatmapInfo Beatmap + { + get => beatmap; + set + { + beatmap = value; + BeatmapID = value?.OnlineBeatmapID ?? 0; + } + } [JsonProperty("beatmap_id")] - public int BeatmapID => Beatmap.OnlineBeatmapID ?? 0; + public int BeatmapID { get; set; } [JsonProperty("ruleset_id")] public int RulesetID { get; set; } @@ -105,37 +118,31 @@ namespace osu.Game.Online.Multiplayer set => _requiredMods = value; } - private RulesetInfo ruleset; - [JsonIgnore] - public RulesetInfo Ruleset + public RulesetInfo Ruleset { get; set; } + + public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) { - get => ruleset; - set + // If we don't have an api beatmap, the request occurred as a result of room creation, so we can query the local beatmap instead + // Todo: Is this a bug? + Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets); + Ruleset = rulesets.GetRuleset(RulesetID); + + if (_allowedMods != null) { - ruleset = value; + AllowedMods.Clear(); + AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); - if (_allowedMods != null) - { - AllowedMods.Clear(); - AllowedMods.AddRange(value.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); - - _allowedMods = null; - } - - if (_requiredMods != null) - { - RequiredMods.Clear(); - RequiredMods.AddRange(value.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); - - _requiredMods = null; - } + _allowedMods = null; } - } - public void SetRulesets(RulesetStore rulesets) - { - Beatmap = beatmap.ToBeatmap(rulesets); + if (_requiredMods != null) + { + RequiredMods.Clear(); + RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); + + _requiredMods = null; + } } // Todo: Move this elsewhere for reusability diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index fead90f9a2..7e29aacaf4 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -63,11 +63,7 @@ namespace osu.Game.Screens.Multi { foreach (var r in result) { - foreach (var pi in r.Playlist) - { - pi.Ruleset = rulesets.GetRuleset(pi.RulesetID); - pi.SetRulesets(rulesets); - } + processPlaylist(r); var existing = rooms.FirstOrDefault(e => e.RoomID.Value == r.RoomID.Value); if (existing == null) @@ -88,6 +84,8 @@ namespace osu.Game.Screens.Multi private void addRoom(Room local, Room remote) { + processPlaylist(remote); + local.CopyFrom(remote); var existing = rooms.FirstOrDefault(e => e.RoomID.Value == local.RoomID.Value); @@ -96,6 +94,12 @@ namespace osu.Game.Screens.Multi rooms.Add(local); } + private void processPlaylist(Room room) + { + foreach (var pi in room.Playlist) + pi.MapObjects(beatmaps, rulesets); + } + private class CreateRoomRequest : APIRequest { private readonly Room room; From bf8aae8d9bc0ee44afaa4ae5b7e6b7e9b4eabc8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Dec 2018 11:51:12 +0900 Subject: [PATCH 160/355] Boot player back to lobby if token request fails --- .../Screens/Multi/Play/TimeshiftPlayer.cs | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 5a9fab6aaf..5d45615aa8 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.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.Diagnostics; using System.Net.Http; +using System.Threading; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.IO.Network; +using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Scoring; using osu.Game.Screens.Play; @@ -25,24 +28,44 @@ namespace osu.Game.Screens.Multi.Play this.playlistItemId = playlistItemId; } - private int token; + private int? token; [BackgroundDependencyLoader] private void load() { + token = null; + + bool failed = false; + var req = new CreateScoreRequest(roomId, playlistItemId); req.Success += r => token = r.ID; - req.Failure += e => { }; + req.Failure += e => + { + failed = true; + + Logger.Error(e, "Failed to retrieve a score submission token."); + + Schedule(() => + { + ValidForResume = false; + Exit(); + }); + }; + api.Queue(req); + + while (!failed && !token.HasValue) + Thread.Sleep(1000); } protected override ScoreInfo CreateScore() { var score = base.CreateScore(); - var request = new SubmitScoreRequest(token, roomId, playlistItemId, score); - request.Success += () => { }; - request.Failure += e => { }; + Debug.Assert(token != null); + + var request = new SubmitScoreRequest(token.Value, roomId, playlistItemId, score); + request.Failure += e => Logger.Error(e, "Failed to submit score"); api.Queue(request); return score; From 84552b5cee34a159b4ef7e2ed755256fbc4bd392 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Dec 2018 11:51:28 +0900 Subject: [PATCH 161/355] Refresh leaderboard when returning to lobby --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index e4e8f8e305..ecb5ced5fa 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; @@ -41,6 +42,7 @@ namespace osu.Game.Screens.Multi.Match private readonly Components.Header header; private readonly Info info; + private readonly MatchLeaderboard leaderboard; [Cached] private readonly Room room; @@ -86,7 +88,7 @@ namespace osu.Game.Screens.Multi.Match new Drawable[] { participants = new Participants { RelativeSizeAxes = Axes.Both }, - new MatchLeaderboard(room) { RelativeSizeAxes = Axes.Both } + leaderboard = new MatchLeaderboard(room) { RelativeSizeAxes = Axes.Both } }, }, ColumnDimensions = new[] @@ -144,6 +146,13 @@ namespace osu.Game.Screens.Multi.Match playlistBind.BindTo(room.Playlist); } + protected override void OnResuming(Screen last) + { + base.OnResuming(last); + + leaderboard.RefreshScores(); + } + private void addPlaylistItem(PlaylistItem item) { playlistBind.Clear(); From 279891ae083548873791deaf067008e86785c639 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Dec 2018 13:55:39 +0900 Subject: [PATCH 162/355] Change "apply" button to say "create" instead --- .../Screens/Multi/Match/Components/RoomSettingsOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index d6098674c1..4d5f572531 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -134,7 +134,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, }, }, - ApplyButton = new ApplySettingsButton + ApplyButton = new CreateRoomButton { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, @@ -276,11 +276,11 @@ namespace osu.Game.Screens.Multi.Match.Components } } - private class ApplySettingsButton : TriangleButton + private class CreateRoomButton : TriangleButton { - public ApplySettingsButton() + public CreateRoomButton() { - Text = "Apply"; + Text = "Create"; } [BackgroundDependencyLoader] From 00998d54432abb578b711a441cb1badb4ede0ba0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Dec 2018 14:29:11 +0900 Subject: [PATCH 163/355] Fix web requests not getting correctly handled on first connection --- osu.Game/Online/API/APIAccess.cs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index a1376b8b94..57dd4f1568 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -141,7 +141,7 @@ namespace osu.Game.Online.API State = APIState.Online; }; - if (!handleRequest(userReq)) + if (!handleRequest(userReq, out _)) { Thread.Sleep(500); continue; @@ -170,11 +170,15 @@ namespace osu.Game.Online.API lock (queue) { if (queue.Count == 0) break; - req = queue.Dequeue(); + req = queue.Peek(); } // TODO: handle failures better - handleRequest(req); + handleRequest(req, out var removeFromQueue); + + if (removeFromQueue) + lock (queue) + queue.Dequeue(); } Thread.Sleep(50); @@ -193,9 +197,11 @@ namespace osu.Game.Online.API /// Handle a single API request. /// /// The request. - /// true if we should remove this request from the queue. - private bool handleRequest(APIRequest req) + /// true if the request succeeded. + private bool handleRequest(APIRequest req, out bool removeFromQueue) { + removeFromQueue = true; + try { Logger.Log($@"Performing request {req}", LoggingTarget.Network); @@ -216,12 +222,12 @@ namespace osu.Game.Online.API } catch (WebException we) { - var removeFromQueue = handleWebException(we); + removeFromQueue = handleWebException(we); if (removeFromQueue) req.Fail(we); - return removeFromQueue; + return false; } catch (Exception e) { @@ -229,7 +235,7 @@ namespace osu.Game.Online.API log.Add(@"API level timeout exception was hit"); req.Fail(e); - return true; + return false; } } From cc68cf2f9546a56d9b5a460d1f4e6b8bdf2183a6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Dec 2018 14:44:54 +0900 Subject: [PATCH 164/355] Implement duration --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 7 ++- osu.Game/Online/Multiplayer/Room.cs | 10 +++- .../Match/Components/RoomSettingsOverlay.cs | 52 ++++++++++++++++--- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs index 19e27ddefe..f44c7de721 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual MaxParticipants = { Value = 10 }, }; - Add(overlay = new TestRoomSettingsOverlay + Add(overlay = new TestRoomSettingsOverlay(new Room()) { RelativeSizeAxes = Axes.Both, Height = 0.75f, @@ -84,6 +84,11 @@ namespace osu.Game.Tests.Visual private class TestRoomSettingsOverlay : RoomSettingsOverlay { + public TestRoomSettingsOverlay(Room room) + : base(room) + { + } + public string CurrentName { get => NameField.Text; diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 0317b3c3e8..0b10992ada 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -29,12 +29,18 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("playlist")] public readonly BindableCollection Playlist = new BindableCollection(); - [JsonProperty("duration")] - public readonly Bindable Duration = new Bindable(100); + [JsonIgnore] + public readonly Bindable Duration = new Bindable(TimeSpan.FromMinutes(30)); [JsonIgnore] public readonly Bindable MaxAttempts = new Bindable(); + [JsonProperty("duration")] + private int duration + { + get => (int)Duration.Value.TotalMinutes; + set => Duration.Value = TimeSpan.FromMinutes(value); + } // Todo: Find a better way to do this (https://github.com/ppy/osu-framework/issues/1930) [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] private int? maxAttempts diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index 4d5f572531..a7149fbb6d 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.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 System; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -26,25 +28,28 @@ namespace osu.Game.Screens.Multi.Match.Components private readonly Bindable typeBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); private readonly IBindableCollection playlistBind = new BindableCollection(); + private readonly Bindable durationBind = new Bindable(); private readonly Container content; private readonly OsuSpriteText typeLabel; protected readonly OsuTextBox NameField, MaxParticipantsField; + protected readonly OsuDropdown DurationField; protected readonly RoomAvailabilityPicker AvailabilityPicker; protected readonly GameTypePicker TypePicker; protected readonly TriangleButton ApplyButton; protected readonly OsuPasswordTextBox PasswordField; - [Resolved] + private readonly Room room; + + [Resolved(CanBeNull = true)] private RoomManager manager { get; set; } - [Resolved] - private Room room { get; set; } - - public RoomSettingsOverlay() + public RoomSettingsOverlay(Room room) { + this.room = room; + Masking = true; Child = content = new Container @@ -121,6 +126,26 @@ namespace osu.Game.Screens.Multi.Match.Components OnCommit = (sender, text) => apply(), }, }, + new Section("DURATION") + { + Child = DurationField = new DurationDropdown + { + RelativeSizeAxes = Axes.X, + Items = new[] + { + TimeSpan.FromMinutes(30), + TimeSpan.FromHours(1), + TimeSpan.FromHours(2), + TimeSpan.FromHours(4), + TimeSpan.FromHours(8), + TimeSpan.FromHours(12), + TimeSpan.FromHours(16), + TimeSpan.FromHours(24), + TimeSpan.FromDays(3), + TimeSpan.FromDays(7) + } + } + }, new Section("PASSWORD (OPTIONAL)") { Child = PasswordField = new SettingsPasswordTextBox @@ -151,6 +176,7 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityBind.ValueChanged += a => AvailabilityPicker.Current.Value = a; typeBind.ValueChanged += t => TypePicker.Current.Value = t; maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); + durationBind.ValueChanged += d => DurationField.Current.Value = d; } [BackgroundDependencyLoader] @@ -163,6 +189,7 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityBind.BindTo(room.Availability); typeBind.BindTo(room.Type); maxParticipantsBind.BindTo(room.MaxParticipants); + durationBind.BindTo(room.Duration); MaxParticipantsField.ReadOnly = true; PasswordField.ReadOnly = true; @@ -210,7 +237,7 @@ namespace osu.Game.Screens.Multi.Match.Components else maxParticipantsBind.Value = null; - manager.CreateRoom(room); + manager?.CreateRoom(room); } private class SettingsTextBox : OsuTextBox @@ -291,5 +318,18 @@ namespace osu.Game.Screens.Multi.Match.Components Triangles.ColourDark = colours.YellowDark; } } + + private class DurationDropdown : OsuDropdown + { + public DurationDropdown() + { + Menu.MaxHeight = 100; + } + + protected override string GenerateItemText(TimeSpan item) + { + return item.Humanize(); + } + } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index ecb5ced5fa..812f20f377 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -110,7 +110,7 @@ namespace osu.Game.Screens.Multi.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Components.Header.HEIGHT }, - Child = settings = new RoomSettingsOverlay + Child = settings = new RoomSettingsOverlay(room) { RelativeSizeAxes = Axes.Both, Height = 0.9f, From 7c4fd8ca60c39039466b7a6738c9de0f790aa4b1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Dec 2018 14:45:06 +0900 Subject: [PATCH 165/355] Cleanup room definition --- .../Online/API/Requests/Responses/APIMod.cs | 12 ++ osu.Game/Online/Multiplayer/PlaylistItem.cs | 93 +++++++++++++ osu.Game/Online/Multiplayer/Room.cs | 123 ++++-------------- 3 files changed, 127 insertions(+), 101 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Responses/APIMod.cs create mode 100644 osu.Game/Online/Multiplayer/PlaylistItem.cs diff --git a/osu.Game/Online/API/Requests/Responses/APIMod.cs b/osu.Game/Online/API/Requests/Responses/APIMod.cs new file mode 100644 index 0000000000..af0d0c643f --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIMod.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIMod : IMod + { + public string Acronym { get; set; } + } +} diff --git a/osu.Game/Online/Multiplayer/PlaylistItem.cs b/osu.Game/Online/Multiplayer/PlaylistItem.cs new file mode 100644 index 0000000000..e887295f4a --- /dev/null +++ b/osu.Game/Online/Multiplayer/PlaylistItem.cs @@ -0,0 +1,93 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using Newtonsoft.Json; +using osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Online.Multiplayer +{ + public class PlaylistItem + { + [JsonProperty("id")] + public int ID { get; set; } + + [JsonProperty("beatmap_id")] + public int BeatmapID { get; set; } + + [JsonProperty("ruleset_id")] + public int RulesetID { get; set; } + + [JsonIgnore] + public BeatmapInfo Beatmap + { + get => beatmap; + set + { + beatmap = value; + BeatmapID = value?.OnlineBeatmapID ?? 0; + } + } + + [JsonIgnore] + public RulesetInfo Ruleset { get; set; } + + [JsonIgnore] + public readonly BindableCollection AllowedMods = new BindableCollection(); + + [JsonIgnore] + public readonly BindableCollection RequiredMods = new BindableCollection(); + + [JsonProperty("beatmap")] + private APIBeatmap apiBeatmap { get; set; } + + [JsonProperty("allowed_mods")] + private APIMod[] allowedMods + { + get => AllowedMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); + set => _allowedMods = value; + } + + [JsonProperty("required_mods")] + private APIMod[] requiredMods + { + get => RequiredMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); + set => _requiredMods = value; + } + + private BeatmapInfo beatmap; + private APIMod[] _allowedMods; + private APIMod[] _requiredMods; + + public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) + { + // If we don't have an api beatmap, the request occurred as a result of room creation, so we can query the local beatmap instead + // Todo: Is this a bug? + Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets); + Ruleset = rulesets.GetRuleset(RulesetID); + + if (_allowedMods != null) + { + AllowedMods.Clear(); + AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); + + _allowedMods = null; + } + + if (_requiredMods != null) + { + RequiredMods.Clear(); + RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); + + _requiredMods = null; + } + } + + public bool ShouldSerializeID() => false; + public bool ShouldSerializeapiBeatmap() => false; + } +} diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 0b10992ada..ed85e6c31c 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -1,14 +1,11 @@ // 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 Newtonsoft.Json; using osu.Framework.Configuration; -using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osu.Game.Users; namespace osu.Game.Online.Multiplayer @@ -16,15 +13,13 @@ namespace osu.Game.Online.Multiplayer public class Room { [JsonProperty("id")] - public Bindable RoomID { get; } = new Bindable(); + public Bindable RoomID { get; private set; } = new Bindable(); [JsonProperty("name")] - public readonly Bindable Name = new Bindable("My awesome room!"); + public Bindable Name { get; private set; } = new Bindable("My awesome room!"); [JsonProperty("host")] - public readonly Bindable Host = new Bindable(); - - public bool ShouldSerializeHost() => false; + public Bindable Host { get; private set; } = new Bindable(); [JsonProperty("playlist")] public readonly BindableCollection Playlist = new BindableCollection(); @@ -35,12 +30,28 @@ namespace osu.Game.Online.Multiplayer [JsonIgnore] public readonly Bindable MaxAttempts = new Bindable(); + [JsonIgnore] + public Bindable Status = new Bindable(new RoomStatusOpen()); + + [JsonIgnore] + public Bindable Availability = new Bindable(); + + [JsonIgnore] + public Bindable Type = new Bindable(new GameTypeTimeshift()); + + [JsonIgnore] + public Bindable MaxParticipants = new Bindable(); + + [JsonIgnore] + public Bindable> Participants = new Bindable>(Enumerable.Empty()); + [JsonProperty("duration")] private int duration { get => (int)Duration.Value.TotalMinutes; set => Duration.Value = TimeSpan.FromMinutes(value); } + // Todo: Find a better way to do this (https://github.com/ppy/osu-framework/issues/1930) [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] private int? maxAttempts @@ -49,12 +60,6 @@ namespace osu.Game.Online.Multiplayer set => MaxAttempts.Value = value; } - public Bindable Status = new Bindable(new RoomStatusOpen()); - public Bindable Availability = new Bindable(); - public Bindable Type = new Bindable(new GameTypeTimeshift()); - public Bindable MaxParticipants = new Bindable(); - public Bindable> Participants = new Bindable>(Enumerable.Empty()); - public void CopyFrom(Room other) { RoomID.Value = other.RoomID; @@ -69,92 +74,8 @@ namespace osu.Game.Online.Multiplayer Playlist.Clear(); Playlist.AddRange(other.Playlist); } - } - public class PlaylistItem - { - [JsonProperty("id")] - public int ID { get; set; } - - [JsonProperty("beatmap")] - private APIBeatmap apiBeatmap { get; set; } - - public bool ShouldSerializeapiBeatmap() => false; - - private BeatmapInfo beatmap; - - [JsonIgnore] - public BeatmapInfo Beatmap - { - get => beatmap; - set - { - beatmap = value; - BeatmapID = value?.OnlineBeatmapID ?? 0; - } - } - - [JsonProperty("beatmap_id")] - public int BeatmapID { get; set; } - - [JsonProperty("ruleset_id")] - public int RulesetID { get; set; } - - [JsonIgnore] - public readonly BindableCollection AllowedMods = new BindableCollection(); - - [JsonIgnore] - public readonly BindableCollection RequiredMods = new BindableCollection(); - - private APIMod[] _allowedMods; - - [JsonProperty("allowed_mods")] - private APIMod[] allowedMods - { - get => AllowedMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); - set => _allowedMods = value; - } - - private APIMod[] _requiredMods; - - [JsonProperty("required_mods")] - private APIMod[] requiredMods - { - get => RequiredMods.Select(m => new APIMod { Acronym = m.Acronym }).ToArray(); - set => _requiredMods = value; - } - - [JsonIgnore] - public RulesetInfo Ruleset { get; set; } - - public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) - { - // If we don't have an api beatmap, the request occurred as a result of room creation, so we can query the local beatmap instead - // Todo: Is this a bug? - Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets); - Ruleset = rulesets.GetRuleset(RulesetID); - - if (_allowedMods != null) - { - AllowedMods.Clear(); - AllowedMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _allowedMods.Any(m => m.Acronym == mod.Acronym))); - - _allowedMods = null; - } - - if (_requiredMods != null) - { - RequiredMods.Clear(); - RequiredMods.AddRange(Ruleset.CreateInstance().GetAllMods().Where(mod => _requiredMods.Any(m => m.Acronym == mod.Acronym))); - - _requiredMods = null; - } - } - - // Todo: Move this elsewhere for reusability - private class APIMod : IMod - { - public string Acronym { get; set; } - } + public bool ShouldSerializeRoomID() => false; + public bool ShouldSerializeHost() => false; } } From 8d640cdc25e50141dfeb49294c6c36060384d259 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 12:56:16 +0900 Subject: [PATCH 166/355] Fix leaderboard not being refreshed when finishing gameplay --- osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 2 +- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 10 +++++++--- osu.Game/Screens/Multi/Match/MatchScreen.cs | 20 ++++++++----------- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index e416000f31..deb098e97d 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual LoungeScreen loungeScreen; Children = new Drawable[] { - loungeScreen = new LoungeScreen + loungeScreen = new LoungeScreen(null) { Padding = new MarginPadding { Top = Header.HEIGHT }, }, diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 1b49e0c1b3..f7dfd73b85 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.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; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,6 +21,7 @@ namespace osu.Game.Screens.Multi.Lounge private readonly Container content; private readonly SearchContainer search; private readonly RoomsContainer rooms; + private readonly Action pushGameplayScreen; [Cached] private readonly RoomManager manager; @@ -28,8 +30,10 @@ namespace osu.Game.Screens.Multi.Lounge protected override Drawable TransitionContent => content; - public LoungeScreen() + public LoungeScreen(Action pushGameplayScreen) { + this.pushGameplayScreen = pushGameplayScreen; + RoomInspector inspector; Children = new Drawable[] @@ -122,7 +126,7 @@ namespace osu.Game.Screens.Multi.Lounge if (Filter.Tabs.Current.Value == LoungeTab.Create) { Filter.Tabs.Current.Value = LoungeTab.Public; - Push(new MatchScreen(new Room())); + openRoom(new Room()); } search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; @@ -136,7 +140,7 @@ namespace osu.Game.Screens.Multi.Lounge if (!IsCurrentScreen) return; - Push(new MatchScreen(room)); + Push(new MatchScreen(room, s => pushGameplayScreen?.Invoke(s))); } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 812f20f377..3f976cb9e2 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.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; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -43,22 +44,21 @@ namespace osu.Game.Screens.Multi.Match private readonly Components.Header header; private readonly Info info; private readonly MatchLeaderboard leaderboard; + private readonly Action pushGameplayScreen; [Cached] private readonly Room room; - [Resolved] - private Multiplayer multiplayer { get; set; } - [Resolved] private BeatmapManager beatmapManager { get; set; } [Resolved] private APIAccess api { get; set; } - public MatchScreen(Room room) + public MatchScreen(Room room, Action pushGameplayScreen) { this.room = room; + this.pushGameplayScreen = pushGameplayScreen; nameBind.BindTo(room.Name); statusBind.BindTo(room.Status); @@ -146,13 +146,6 @@ namespace osu.Game.Screens.Multi.Match playlistBind.BindTo(room.Playlist); } - protected override void OnResuming(Screen last) - { - base.OnResuming(last); - - leaderboard.RefreshScores(); - } - private void addPlaylistItem(PlaylistItem item) { playlistBind.Clear(); @@ -192,7 +185,10 @@ namespace osu.Game.Screens.Multi.Match { default: case GameTypeTimeshift _: - multiplayer.Push(new PlayerLoader(new TimeshiftPlayer(room.RoomID.Value ?? 0, room.Playlist.First().ID))); + var player = new TimeshiftPlayer(room.RoomID.Value ?? 0, room.Playlist.First().ID); + player.Exited += _ => leaderboard.RefreshScores(); + + pushGameplayScreen?.Invoke(new PlayerLoader(player)); break; } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 0169d32c75..73a27a2b0a 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Multi { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = loungeScreen = new LoungeScreen(), + Child = loungeScreen = new LoungeScreen(Push), }, new Header(loungeScreen) }); From 5a8b255bd84661ee25a42156577dce158cdfe31c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 14:17:20 +0900 Subject: [PATCH 167/355] Directly bypass beatmap/ruleset restrictions --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 25 +++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 3f976cb9e2..3547534dfb 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -32,10 +32,9 @@ namespace osu.Game.Screens.Multi.Match private readonly Bindable> participantsBind = new Bindable>(); private readonly BindableCollection playlistBind = new BindableCollection(); - protected override Drawable TransitionContent => participants; + public override bool AllowBeatmapRulesetChange => false; - public override bool AllowBeatmapRulesetChange => allowBeatmapRulesetChange; - private bool allowBeatmapRulesetChange; + protected override Drawable TransitionContent => participants; public override string Title => room.Name.Value; @@ -164,19 +163,21 @@ namespace osu.Game.Screens.Multi.Match info.Beatmap.Value = item.Beatmap; info.Mods.Value = item.RequiredMods; - allowBeatmapRulesetChange = true; - // Todo: item.Beatmap can be null here... var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; - Schedule(() => - { - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); - Ruleset.Value = item.Ruleset; + // Bypass any beatmap and ruleset restrictions + var beatmapDisabled = Beatmap.Disabled; + var rulesetDisabled = Ruleset.Disabled; + Beatmap.Disabled = false; + Ruleset.Disabled = false; - allowBeatmapRulesetChange = false; - }); + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); + Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); + Ruleset.Value = item.Ruleset; + + Beatmap.Disabled = beatmapDisabled; + Ruleset.Disabled = rulesetDisabled; } private void onStart() From 2f15d100298b69bfe726c2c1a6ef0440b343abb6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 14:45:35 +0900 Subject: [PATCH 168/355] Play track while in the multiplayer lobby --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 3547534dfb..4c09c59804 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -178,6 +178,10 @@ namespace osu.Game.Screens.Multi.Match Beatmap.Disabled = beatmapDisabled; Ruleset.Disabled = rulesetDisabled; + + Beatmap.Value.Track.Looping = true; + Beatmap.Value.Track.Seek(Beatmap.Value.Metadata.PreviewTime); + Beatmap.Value.Track.Start(); } private void onStart() From aabe6c68f54b181b4a81024280d75364b0b7df9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 17:07:47 +0900 Subject: [PATCH 169/355] Fix looping not working --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 4 --- osu.Game/Screens/Multi/Multiplayer.cs | 34 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 4c09c59804..3547534dfb 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -178,10 +178,6 @@ namespace osu.Game.Screens.Multi.Match Beatmap.Disabled = beatmapDisabled; Ruleset.Disabled = rulesetDisabled; - - Beatmap.Value.Track.Looping = true; - Beatmap.Value.Track.Seek(Beatmap.Value.Metadata.PreviewTime); - Beatmap.Value.Track.Start(); } private void onStart() diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 73a27a2b0a..0d618464b5 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Screens.Menu; using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Match; namespace osu.Game.Screens.Multi { @@ -76,6 +77,11 @@ namespace osu.Game.Screens.Multi protected override bool OnExiting(Screen next) { waves.Hide(); + + var track = Beatmap.Value.Track; + if (track != null) + track.Looping = false; + return base.OnExiting(next); } @@ -102,6 +108,27 @@ namespace osu.Game.Screens.Multi base.LogoExiting(logo); } + protected override void Update() + { + base.Update(); + + if (currentScreen is MatchScreen) + { + var track = Beatmap.Value.Track; + if (track != null) + { + track.Looping = true; + + if (!track.IsRunning) + { + Game.Audio.AddItemToList(track); + track.Seek(Beatmap.Value.Metadata.PreviewTime); + track.Start(); + } + } + } + } + private void screenAdded(Screen newScreen) { currentScreen = (OsuScreen)newScreen; @@ -112,6 +139,13 @@ namespace osu.Game.Screens.Multi private void screenRemoved(Screen newScreen) { + if (currentScreen is MatchScreen) + { + var track = Beatmap.Value.Track; + if (track != null) + track.Looping = false; + } + currentScreen = (OsuScreen)newScreen; } From e4e1bde5dae2f6f14066696f206d4393801141ac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 17:08:02 +0900 Subject: [PATCH 170/355] Fix playlist events running too early Screens are async loaded --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 3547534dfb..ae6e4c7ff9 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -139,9 +139,10 @@ namespace osu.Game.Screens.Multi.Match playlistBind.ItemsRemoved += _ => setFromPlaylist(); } - [BackgroundDependencyLoader] - private void load() + protected override void LoadComplete() { + base.LoadComplete(); + playlistBind.BindTo(room.Playlist); } From 3cdeeb7ac5d156ce3c15f67142872cd858373289 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 18:09:46 +0900 Subject: [PATCH 171/355] Add forceful set helper methods in OsuGame --- osu.Game/OsuGame.cs | 26 +++++++++++++++++++++ osu.Game/Screens/Multi/Match/MatchScreen.cs | 18 ++++++-------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 31a00e68ac..51520a1606 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -671,6 +671,32 @@ namespace osu.Game MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; } + /// + /// Sets while ignoring any beatmap. + /// + /// The beatmap to set. + public void ForcefullySetBeatmap(WorkingBeatmap beatmap) + { + var beatmapDisabled = Beatmap.Disabled; + + Beatmap.Disabled = false; + Beatmap.Value = beatmap; + Beatmap.Disabled = beatmapDisabled; + } + + /// + /// Sets while ignoring any ruleset restrictions. + /// + /// The beatmap to set. + public void ForcefullySetRuleset(RulesetInfo ruleset) + { + var rulesetDisabled = this.ruleset.Disabled; + + this.ruleset.Disabled = false; + this.ruleset.Value = ruleset; + this.ruleset.Disabled = rulesetDisabled; + } + private void screenAdded(Screen newScreen) { currentScreen = (OsuScreen)newScreen; diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index ae6e4c7ff9..da160b985c 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -54,6 +54,9 @@ namespace osu.Game.Screens.Multi.Match [Resolved] private APIAccess api { get; set; } + [Resolved] + private OsuGame game { get; set; } + public MatchScreen(Room room, Action pushGameplayScreen) { this.room = room; @@ -167,18 +170,11 @@ namespace osu.Game.Screens.Multi.Match // Todo: item.Beatmap can be null here... var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; - // Bypass any beatmap and ruleset restrictions - var beatmapDisabled = Beatmap.Disabled; - var rulesetDisabled = Ruleset.Disabled; - Beatmap.Disabled = false; - Ruleset.Disabled = false; + var newBeatmap = beatmapManager.GetWorkingBeatmap(localBeatmap); + newBeatmap.Mods.Value = item.RequiredMods.ToArray(); - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - Beatmap.Value.Mods.Value = item.RequiredMods.ToArray(); - Ruleset.Value = item.Ruleset; - - Beatmap.Disabled = beatmapDisabled; - Ruleset.Disabled = rulesetDisabled; + game.ForcefullySetBeatmap(newBeatmap); + game.ForcefullySetRuleset(item.Ruleset); } private void onStart() From 4050cb88ea476cce8bf0363d0f9a4c6d9f63e523 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 18:09:54 +0900 Subject: [PATCH 172/355] Fix potential nullref --- osu.Game/Screens/Multi/Match/Components/ReadyButton.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index c52a3be7cb..61ea7cb8fa 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -54,7 +54,8 @@ namespace osu.Game.Screens.Multi.Match.Components { base.Dispose(isDisposing); - beatmaps.ItemAdded -= beatmapAdded; + if (beatmaps != null) + beatmaps.ItemAdded -= beatmapAdded; } } } From 72d1ba897fba0801cfe795247088254f2f145ab9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 18 Dec 2018 18:29:13 +0900 Subject: [PATCH 173/355] Reorder tabs --- osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs index fa760c97e3..538dcc341e 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -21,8 +21,8 @@ namespace osu.Game.Screens.Multi.Match.Components public MatchTabControl() { - AddItem(new SettingsMatchPage()); AddItem(new RoomMatchPage()); + AddItem(new SettingsMatchPage()); } [BackgroundDependencyLoader] From 6088612a266b0fd407d015849262236d0ff548ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Dec 2018 20:19:40 +0900 Subject: [PATCH 174/355] Remove all retry logic and simplify overall handling of API requests --- osu.Game/Online/API/APIAccess.cs | 38 +++++++------------------------ osu.Game/Online/API/APIRequest.cs | 35 ++++++++++------------------ 2 files changed, 20 insertions(+), 53 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 57dd4f1568..7786bb55ac 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -102,7 +102,7 @@ namespace osu.Game.Online.API if (queue.Count == 0) { log.Add(@"Queueing a ping request"); - Queue(new ListChannelsRequest { Timeout = 5000 }); + Queue(new GetUserRequest()); } break; @@ -141,7 +141,7 @@ namespace osu.Game.Online.API State = APIState.Online; }; - if (!handleRequest(userReq, out _)) + if (!handleRequest(userReq)) { Thread.Sleep(500); continue; @@ -170,15 +170,10 @@ namespace osu.Game.Online.API lock (queue) { if (queue.Count == 0) break; - req = queue.Peek(); + req = queue.Dequeue(); } - // TODO: handle failures better - handleRequest(req, out var removeFromQueue); - - if (removeFromQueue) - lock (queue) - queue.Dequeue(); + handleRequest(req); } Thread.Sleep(50); @@ -195,46 +190,29 @@ namespace osu.Game.Online.API /// /// Handle a single API request. + /// Ensures all exceptions are caught and dealt with correctly. /// /// The request. /// true if the request succeeded. - private bool handleRequest(APIRequest req, out bool removeFromQueue) + private bool handleRequest(APIRequest req) { - removeFromQueue = true; - try { - Logger.Log($@"Performing request {req}", LoggingTarget.Network); - req.Failure += ex => - { - if (ex is WebException we) - handleWebException(we); - }; - req.Perform(this); //we could still be in initialisation, at which point we don't want to say we're Online yet. - if (IsLoggedIn) - State = APIState.Online; + if (IsLoggedIn) State = APIState.Online; failureCount = 0; return true; } catch (WebException we) { - removeFromQueue = handleWebException(we); - - if (removeFromQueue) - req.Fail(we); - + handleWebException(we); return false; } catch (Exception e) { - if (e is TimeoutException) - log.Add(@"API level timeout exception was hit"); - - req.Fail(e); return false; } } diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index adbedb2aac..41f774e83c 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.IO.Network; +using osu.Framework.Logging; namespace osu.Game.Online.API { @@ -35,23 +36,12 @@ namespace osu.Game.Online.API /// public abstract class APIRequest { - /// - /// The maximum amount of time before this request will fail. - /// - public int Timeout = WebRequest.DEFAULT_TIMEOUT; - protected virtual string Target => string.Empty; protected virtual WebRequest CreateWebRequest() => new WebRequest(Uri); protected virtual string Uri => $@"{API.Endpoint}/api/v2/{Target}"; - private double remainingTime => Math.Max(0, Timeout - (DateTimeOffset.UtcNow - (startTime ?? DateTimeOffset.MinValue)).TotalMilliseconds); - - public bool ExceededTimeout => remainingTime == 0; - - private DateTimeOffset? startTime; - protected APIAccess API; protected WebRequest WebRequest; @@ -75,27 +65,24 @@ namespace osu.Game.Online.API { API = api; - if (checkAndProcessFailure()) + if (checkAndScheduleFailure()) return; - if (startTime == null) - startTime = DateTimeOffset.UtcNow; - - if (remainingTime <= 0) - throw new TimeoutException(@"API request timeout hit"); - WebRequest = CreateWebRequest(); WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; WebRequest.AddHeader("Authorization", $"Bearer {api.AccessToken}"); - if (checkAndProcessFailure()) + if (checkAndScheduleFailure()) return; if (!WebRequest.Aborted) //could have been aborted by a Cancel() call + { + Logger.Log($@"Performing request {this}", LoggingTarget.Network); WebRequest.Perform(); + } - if (checkAndProcessFailure()) + if (checkAndScheduleFailure()) return; api.Schedule(delegate { Success?.Invoke(); }); @@ -105,19 +92,21 @@ namespace osu.Game.Online.API public void Fail(Exception e) { - cancelled = true; + if (cancelled) return; + cancelled = true; WebRequest?.Abort(); + Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network); pendingFailure = () => Failure?.Invoke(e); - checkAndProcessFailure(); + checkAndScheduleFailure(); } /// /// Checked for cancellation or error. Also queues up the Failed event if we can. /// /// Whether we are in a failed or cancelled state. - private bool checkAndProcessFailure() + private bool checkAndScheduleFailure() { if (API == null || pendingFailure == null) return cancelled; From 4a1af67893d7959ebe77353ec5cf63afa8d0407f Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 18 Dec 2018 22:49:53 +0300 Subject: [PATCH 175/355] Do not delete file on import failure --- osu.Game/Database/ArchiveModelManager.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 50767608af..77e92421e9 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -149,8 +149,10 @@ namespace osu.Game.Database try { notification.Text = $"Importing ({++current} of {paths.Length})\n{Path.GetFileName(path)}"; + + TModel import; using (ArchiveReader reader = getReaderFrom(path)) - imported.Add(Import(reader)); + imported.Add(import = Import(reader)); notification.Progress = (float)current / paths.Length; @@ -160,7 +162,7 @@ namespace osu.Game.Database // TODO: Add a check to prevent files from storage to be deleted. try { - if (File.Exists(path)) + if (import != null && File.Exists(path)) File.Delete(path); } catch (Exception e) From bacc07f5ec3ed6e873a6872bd1f2b406d6e4d80f Mon Sep 17 00:00:00 2001 From: Styphix Date: Tue, 18 Dec 2018 19:44:31 -0500 Subject: [PATCH 176/355] Changed `OsuFocusedOverlayContainer` to `WaveOverlayContainer` from `ChannelSelectionOverlay` Not sure what colour i shouldve gone for but im certain that this should be fine --- .../Overlays/Chat/Selection/ChannelSelectionOverlay.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 3afac211f1..0cc0076903 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -20,7 +20,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Chat.Selection { - public class ChannelSelectionOverlay : OsuFocusedOverlayContainer + public class ChannelSelectionOverlay : WaveOverlayContainer { public static readonly float WIDTH_PADDING = 170; @@ -39,6 +39,11 @@ namespace osu.Game.Overlays.Chat.Selection { RelativeSizeAxes = Axes.X; + Waves.FirstWaveColour = OsuColour.FromHex("353535"); + Waves.SecondWaveColour = OsuColour.FromHex("434343"); + Waves.ThirdWaveColour = OsuColour.FromHex("515151"); + Waves.FourthWaveColour = OsuColour.FromHex("595959"); + Children = new Drawable[] { new Container From 1051584f0f6972094735566a82aab9dd1bd5cf3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 10:51:54 +0900 Subject: [PATCH 177/355] Fix room duration not being set --- osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index a7149fbb6d..d3098efb82 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -237,6 +237,8 @@ namespace osu.Game.Screens.Multi.Match.Components else maxParticipantsBind.Value = null; + durationBind.Value = DurationField.Current.Value; + manager?.CreateRoom(room); } From 2c000a9a1d51d14e389bda0fd498566acb15620b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 10:52:15 +0900 Subject: [PATCH 178/355] Disallow starting gameplay if there's not enough time in the room --- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 2 +- osu.Game/Online/Multiplayer/Room.cs | 6 +++ .../Screens/Multi/Match/Components/Info.cs | 4 +- .../Multi/Match/Components/ReadyButton.cs | 49 +++++++++++++++---- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 0272581a8f..799b5f2526 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - Info info = new Info(); + Info info = new Info(new Room()); Add(info); AddStep(@"set name", () => info.Name.Value = @"Room Name?"); diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index ed85e6c31c..5249870e35 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -52,6 +52,10 @@ namespace osu.Game.Online.Multiplayer set => Duration.Value = TimeSpan.FromMinutes(value); } + // Only supports retrieval for now + [JsonProperty("ends_at")] + public Bindable EndDate = new Bindable(); + // Todo: Find a better way to do this (https://github.com/ppy/osu-framework/issues/1930) [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] private int? maxAttempts @@ -70,6 +74,7 @@ namespace osu.Game.Online.Multiplayer Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); + EndDate = other.EndDate; Playlist.Clear(); Playlist.AddRange(other.Playlist); @@ -77,5 +82,6 @@ namespace osu.Game.Online.Multiplayer public bool ShouldSerializeRoomID() => false; public bool ShouldSerializeHost() => false; + public bool ShouldSerializeEndDate() => false; } } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index 1750323486..77295a1a13 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Multi.Match.Components public readonly Bindable Type = new Bindable(); public readonly Bindable> Mods = new Bindable>(); - public Info() + public Info(Room room) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Multi.Match.Components Children = new Drawable[] { viewBeatmapButton = new ViewBeatmapButton(), - readyButton = new ReadyButton + readyButton = new ReadyButton(room) { Action = () => OnStart?.Invoke() } diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index 61ea7cb8fa..d3726da246 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -1,11 +1,13 @@ // 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.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; using osuTK; namespace osu.Game.Screens.Multi.Match.Components @@ -14,11 +16,19 @@ namespace osu.Game.Screens.Multi.Match.Components { public readonly IBindable Beatmap = new Bindable(); + private readonly Room room; + + [Resolved] + private IBindableBeatmap gameBeatmap { get; set; } + [Resolved] private BeatmapManager beatmaps { get; set; } - public ReadyButton() + private bool hasBeatmap; + + public ReadyButton(Room room) { + this.room = room; RelativeSizeAxes = Axes.Y; Size = new Vector2(200, 1); @@ -30,24 +40,43 @@ namespace osu.Game.Screens.Multi.Match.Components { beatmaps.ItemAdded += beatmapAdded; - Beatmap.BindValueChanged(updateEnabledState, true); + Beatmap.BindValueChanged(updateBeatmap, true); } - private void updateEnabledState(BeatmapInfo beatmap) + private void updateBeatmap(BeatmapInfo beatmap) { - if (beatmap?.OnlineBeatmapID == null) - { - Enabled.Value = false; - return; - } + hasBeatmap = false; - Enabled.Value = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID) != null; + if (beatmap?.OnlineBeatmapID == null) + return; + + hasBeatmap = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID) != null; } private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) { if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID)) - Schedule(() => Enabled.Value = true); + Schedule(() => hasBeatmap = true); + } + + protected override void Update() + { + base.Update(); + + updateEnabledState(); + } + + private void updateEnabledState() + { + if (gameBeatmap.Value == null) + { + Enabled.Value = false; + return; + } + + bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < room.EndDate; + + Enabled.Value = hasBeatmap && hasEnoughTime; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index da160b985c..7a21a2339a 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Multi.Match Content = new[] { new Drawable[] { header = new Components.Header { Depth = -1 } }, - new Drawable[] { info = new Info { OnStart = onStart } }, + new Drawable[] { info = new Info(room) { OnStart = onStart } }, new Drawable[] { new GridContainer From b89a6bea4c4a710bf87ca7a2c95d5872d1e45333 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 12:44:51 +0900 Subject: [PATCH 179/355] Make DrawableDate adjustable --- osu.Game/Graphics/DrawableDate.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 28f8bdf82f..639a549936 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -4,6 +4,7 @@ using System; using Humanizer; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Sprites; @@ -11,13 +12,27 @@ namespace osu.Game.Graphics { public class DrawableDate : OsuSpriteText, IHasTooltip { - protected readonly DateTimeOffset Date; + private DateTimeOffset date; + + public DateTimeOffset Date + { + get => date; + set + { + if (date == value) + return; + date = value.ToLocalTime(); + + if (LoadState >= LoadState.Ready) + updateTime(); + } + } public DrawableDate(DateTimeOffset date) { Font = "Exo2.0-RegularItalic"; - Date = date.ToLocalTime(); + Date = date; } [BackgroundDependencyLoader] From 224e644aa1eee1ab23241ab4835198fb7b28e5fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 13:07:43 +0900 Subject: [PATCH 180/355] Fix negative dates, and time moving in opposite direction --- osu.Game/Graphics/DrawableDate.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 639a549936..87711c72c7 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -54,14 +54,14 @@ namespace osu.Game.Graphics var diffToNow = DateTimeOffset.Now.Subtract(Date); double timeUntilNextUpdate = 1000; - if (diffToNow.TotalSeconds > 60) + if (Math.Abs(diffToNow.TotalSeconds) > 120) { timeUntilNextUpdate *= 60; - if (diffToNow.TotalMinutes > 60) + if (Math.Abs(diffToNow.TotalMinutes) > 120) { timeUntilNextUpdate *= 60; - if (diffToNow.TotalHours > 24) + if (Math.Abs(diffToNow.TotalHours) > 48) timeUntilNextUpdate *= 24; } } From a8d88dea3b26c1d33f6f6571e7c33a3634b36783 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 13:07:56 +0900 Subject: [PATCH 181/355] Display time remaining in the room --- osu.Game/Online/Multiplayer/Room.cs | 2 +- .../Screens/Multi/Match/Components/Info.cs | 28 +++++++++++++++++++ osu.Game/Screens/Multi/Match/MatchScreen.cs | 3 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 5249870e35..39319aa32e 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -74,7 +74,7 @@ namespace osu.Game.Online.Multiplayer Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); - EndDate = other.EndDate; + EndDate.Value = other.EndDate; Playlist.Clear(); Playlist.AddRange(other.Playlist); diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index 77295a1a13..9710f4b2fd 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -35,6 +35,7 @@ namespace osu.Game.Screens.Multi.Match.Components public readonly Bindable Beatmap = new Bindable(); public readonly Bindable Type = new Bindable(); public readonly Bindable> Mods = new Bindable>(); + public readonly Bindable EndDate = new Bindable(); public Info(Room room) { @@ -46,6 +47,7 @@ namespace osu.Game.Screens.Multi.Match.Components BeatmapTypeInfo beatmapTypeInfo; OsuSpriteText name; ModDisplay modDisplay; + DrawableDate date; Children = new Drawable[] { @@ -77,6 +79,7 @@ namespace osu.Game.Screens.Multi.Match.Components { name = new OsuSpriteText { TextSize = 30 }, availabilityStatus = new OsuSpriteText { TextSize = 14 }, + date = new MatchDate { TextSize = 14 } } }, new FillFlowContainer @@ -126,6 +129,7 @@ namespace osu.Game.Screens.Multi.Match.Components Availability.BindValueChanged(_ => updateAvailabilityStatus()); Status.BindValueChanged(_ => updateAvailabilityStatus()); Name.BindValueChanged(n => name.Text = n); + EndDate.BindValueChanged(d => date.Date = d); } [BackgroundDependencyLoader] @@ -152,5 +156,29 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityStatus.Text = $"{Availability.Value.GetDescription()}, {Status.Value.Message}"; } } + + private class MatchDate : DrawableDate + { + public MatchDate() + : base(DateTimeOffset.UtcNow) + { + } + + protected override string Format() + { + var diffToNow = Date.Subtract(DateTimeOffset.Now); + + if (diffToNow.TotalSeconds < -5) + return $"Closed {base.Format()}"; + + if (diffToNow.TotalSeconds < 0) + return "Closed"; + + if (diffToNow.TotalSeconds < 5) + return "Closing soon"; + + return $"Closing {base.Format()}"; + } + } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 7a21a2339a..c169a5fb5d 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -31,6 +31,7 @@ namespace osu.Game.Screens.Multi.Match private readonly Bindable maxParticipantsBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); private readonly BindableCollection playlistBind = new BindableCollection(); + private readonly Bindable endDateBind = new Bindable(); public override bool AllowBeatmapRulesetChange => false; @@ -68,6 +69,7 @@ namespace osu.Game.Screens.Multi.Match typeBind.BindTo(room.Type); participantsBind.BindTo(room.Participants); maxParticipantsBind.BindTo(room.MaxParticipants); + endDateBind.BindTo(room.EndDate); RoomSettingsOverlay settings; @@ -134,6 +136,7 @@ namespace osu.Game.Screens.Multi.Match info.Status.BindTo(statusBind); info.Availability.BindTo(availabilityBind); info.Type.BindTo(typeBind); + info.EndDate.BindTo(endDateBind); participants.Users.BindTo(participantsBind); participants.MaxParticipants.BindTo(maxParticipantsBind); From 9d8170efa0b69bcbbbccd172130013d248a43428 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 14:32:43 +0900 Subject: [PATCH 182/355] Only go into failing state if previously online --- osu.Game/Online/API/APIAccess.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 7786bb55ac..cfbcf0326a 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -268,8 +268,12 @@ namespace osu.Game.Online.API //we might try again at an api level. return false; - State = APIState.Failing; - flushQueue(); + if (State == APIState.Online) + { + State = APIState.Failing; + flushQueue(); + } + return true; } From c544a5b9f0ad7afbfc7a5765111d9993f31a9ac2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 15:20:23 +0900 Subject: [PATCH 183/355] Add end date to the drawable room too --- .../Screens/Multi/Components/EndDateInfo.cs | 32 +++++++++++++++++++ .../Multi/Lounge/Components/DrawableRoom.cs | 30 +++++++++++++---- .../Screens/Multi/Match/Components/Info.cs | 30 ++--------------- 3 files changed, 59 insertions(+), 33 deletions(-) create mode 100644 osu.Game/Screens/Multi/Components/EndDateInfo.cs diff --git a/osu.Game/Screens/Multi/Components/EndDateInfo.cs b/osu.Game/Screens/Multi/Components/EndDateInfo.cs new file mode 100644 index 0000000000..c71ec04d33 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/EndDateInfo.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Multi.Components +{ + public class EndDateInfo : DrawableDate + { + public EndDateInfo() + : base(DateTimeOffset.UtcNow) + { + } + + protected override string Format() + { + var diffToNow = Date.Subtract(DateTimeOffset.Now); + + if (diffToNow.TotalSeconds < -5) + return $"Closed {base.Format()}"; + + if (diffToNow.TotalSeconds < 0) + return "Closed"; + + if (diffToNow.TotalSeconds < 5) + return "Closing soon"; + + return $"Closing {base.Format()}"; + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 5cf11e5c98..adcb088f4e 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private const float corner_radius = 5; private const float transition_duration = 60; private const float content_padding = 10; - private const float height = 100; + private const float height = 110; private const float side_strip_width = 5; private const float cover_width = 145; @@ -45,6 +45,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly Bindable typeBind = new Bindable(); private readonly Bindable> participantsBind = new Bindable>(); private readonly IBindableCollection playlistBind = new BindableCollection(); + private readonly IBindable endDateBind = new Bindable(); private readonly Bindable beatmap = new Bindable(); @@ -111,8 +112,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components Box sideStrip; OsuSpriteText status; ParticipantInfo participantInfo; - OsuSpriteText name; + EndDateInfo endDate; Children = new Drawable[] { @@ -189,11 +190,25 @@ namespace osu.Game.Screens.Multi.Lounge.Components TextSize = 14, Font = @"Exo2.0-Bold", }, - beatmapTitle = new BeatmapTitle + new FillFlowContainer { - TextSize = 14, - Colour = colours.Gray9 - }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + endDate = new EndDateInfo + { + TextSize = 14, + }, + beatmapTitle = new BeatmapTitle + { + TextSize = 14, + Colour = colours.Gray9 + }, + } + } }, }, modeTypeInfo = new ModeTypeInfo @@ -224,6 +239,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components typeBind.BindTo(Room.Type); playlistBind.BindTo(Room.Playlist); participantsBind.BindTo(Room.Participants); + endDateBind.BindTo(Room.EndDate); + + endDateBind.BindValueChanged(d => endDate.Date = d, true); modeTypeInfo.Type.BindTo(typeBind); diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index 9710f4b2fd..f63135fc2d 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Multi.Match.Components BeatmapTypeInfo beatmapTypeInfo; OsuSpriteText name; ModDisplay modDisplay; - DrawableDate date; + EndDateInfo endDate; Children = new Drawable[] { @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Multi.Match.Components { name = new OsuSpriteText { TextSize = 30 }, availabilityStatus = new OsuSpriteText { TextSize = 14 }, - date = new MatchDate { TextSize = 14 } + endDate = new EndDateInfo { TextSize = 14 } } }, new FillFlowContainer @@ -129,7 +129,7 @@ namespace osu.Game.Screens.Multi.Match.Components Availability.BindValueChanged(_ => updateAvailabilityStatus()); Status.BindValueChanged(_ => updateAvailabilityStatus()); Name.BindValueChanged(n => name.Text = n); - EndDate.BindValueChanged(d => date.Date = d); + EndDate.BindValueChanged(d => endDate.Date = d); } [BackgroundDependencyLoader] @@ -156,29 +156,5 @@ namespace osu.Game.Screens.Multi.Match.Components availabilityStatus.Text = $"{Availability.Value.GetDescription()}, {Status.Value.Message}"; } } - - private class MatchDate : DrawableDate - { - public MatchDate() - : base(DateTimeOffset.UtcNow) - { - } - - protected override string Format() - { - var diffToNow = Date.Subtract(DateTimeOffset.Now); - - if (diffToNow.TotalSeconds < -5) - return $"Closed {base.Format()}"; - - if (diffToNow.TotalSeconds < 0) - return "Closed"; - - if (diffToNow.TotalSeconds < 5) - return "Closing soon"; - - return $"Closing {base.Format()}"; - } - } } } From 673082445e5470db0e0ed21c8b00c33947d008c3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 16:56:51 +0900 Subject: [PATCH 184/355] Rework filtering --- .../Multi/Lounge/Components/FilterControl.cs | 39 +++++++++---------- .../Multi/Lounge/Components/FilterCriteria.cs | 6 +-- .../Multi/Lounge/Components/RoomsContainer.cs | 21 +++++++++- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 20 ++-------- osu.Game/Screens/Multi/Multiplayer.cs | 26 ++++++++++++- 5 files changed, 70 insertions(+), 42 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index ddab9c197e..01bc23ba4b 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -1,45 +1,42 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.ComponentModel; using osu.Game.Graphics; -using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; namespace osu.Game.Screens.Multi.Lounge.Components { - public class FilterControl : SearchableListFilterControl + public class FilterControl : SearchableListFilterControl { protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42"); - protected override LoungeTab DefaultTab => LoungeTab.Public; + protected override PrimaryFilter DefaultTab => PrimaryFilter.Current; public FilterControl() { DisplayStyleControl.Hide(); } - public FilterCriteria CreateCriteria() => new FilterCriteria { Availability = availability }; - - private RoomAvailability availability + public FilterCriteria CreateCriteria() => new FilterCriteria { - get - { - switch (Tabs.Current.Value) - { - default: - case LoungeTab.Public: - return RoomAvailability.Public; - case LoungeTab.Private: - return RoomAvailability.FriendsOnly; - } - } - } + SearchString = Search.Current.Value ?? string.Empty, + PrimaryFilter = Tabs.Current, + SecondaryFilter = DisplayStyleControl.Dropdown.Current + }; } - public enum LoungeTab + public enum PrimaryFilter + { + Current, + [Description("Recently Ended")] + RecentlyEnded, + Participated, + } + + public enum SecondaryFilter { - Create, Public, - Private, + //Private, } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs index ec62ef1bdf..0a1c8a3e84 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Online.Multiplayer; - namespace osu.Game.Screens.Multi.Lounge.Components { public class FilterCriteria { - public RoomAvailability Availability; + public string SearchString; + public PrimaryFilter PrimaryFilter; + public SecondaryFilter SecondaryFilter; } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 072a892954..af66f5bfe8 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -59,7 +59,26 @@ namespace osu.Game.Screens.Multi.Lounge.Components public void Filter(FilterCriteria criteria) { - roomFlow.Children.ForEach(r => r.MatchingFilter = criteria == null || r.Room.Availability == criteria.Availability); + roomFlow.Children.ForEach(r => + { + if (criteria == null) + r.MatchingFilter = true; + else + { + bool matchingFilter = true; + matchingFilter &= r.FilterTerms.Any(term => term.IndexOf(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase) >= 0); + + switch (criteria.SecondaryFilter) + { + default: + case SecondaryFilter.Public: + r.MatchingFilter = r.Room.Availability.Value == RoomAvailability.Public; + break; + } + + r.MatchingFilter = matchingFilter; + } + }); currentFilter = criteria; } diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index f7dfd73b85..81a478b778 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -19,7 +19,6 @@ namespace osu.Game.Screens.Multi.Lounge protected readonly FilterControl Filter; private readonly Container content; - private readonly SearchContainer search; private readonly RoomsContainer rooms; private readonly Action pushGameplayScreen; @@ -53,11 +52,11 @@ namespace osu.Game.Screens.Multi.Lounge Vertical = 35 - DrawableRoom.SELECTION_BORDER_WIDTH, Right = 20 - DrawableRoom.SELECTION_BORDER_WIDTH }, - Child = search = new SearchContainer + Child = new SearchContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = rooms = new RoomsContainer { OpenRequested = openRoom } + Child = rooms = new RoomsContainer { OpenRequested = Open } }, }, inspector = new RoomInspector @@ -121,20 +120,9 @@ namespace osu.Game.Screens.Multi.Lounge Filter.Search.HoldFocus = false; } - private void filterRooms() - { - if (Filter.Tabs.Current.Value == LoungeTab.Create) - { - Filter.Tabs.Current.Value = LoungeTab.Public; - openRoom(new Room()); - } + private void filterRooms() => rooms.Filter(Filter.CreateCriteria()); - search.SearchTerm = Filter.Search.Current.Value ?? string.Empty; - - rooms.Filter(Filter.CreateCriteria()); - } - - private void openRoom(Room room) + public void Open(Room room) { // Handles the case where a room is clicked 3 times in quick succession if (!IsCurrentScreen) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 0d618464b5..4a0fa141c8 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -9,9 +9,13 @@ using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Screens.Menu; using osu.Game.Screens.Multi.Lounge; using osu.Game.Screens.Multi.Match; +using osuTK; namespace osu.Game.Screens.Multi { @@ -22,6 +26,8 @@ namespace osu.Game.Screens.Multi public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; + private readonly OsuButton createButton; + private OsuScreen currentScreen; public Multiplayer() @@ -60,7 +66,21 @@ namespace osu.Game.Screens.Multi Padding = new MarginPadding { Top = Header.HEIGHT }, Child = loungeScreen = new LoungeScreen(Push), }, - new Header(loungeScreen) + new Header(loungeScreen), + createButton = new HeaderButton + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.None, + Size = new Vector2(150, Header.HEIGHT - 20), + Margin = new MarginPadding + { + Top = 10, + Right = 10, + }, + Text = "Create room", + Action = () => loungeScreen.Open(new Room()) + } }); screenAdded(loungeScreen); @@ -126,7 +146,11 @@ namespace osu.Game.Screens.Multi track.Start(); } } + + createButton.Hide(); } + else + createButton.Show(); } private void screenAdded(Screen newScreen) From c86d9533bd86049314d3fef74f7cfe4628e98c24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 18:01:21 +0900 Subject: [PATCH 185/355] Add PollImmediately() --- osu.Game/Online/PollingComponent.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index d9dcfc40c2..7e5ed31491 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -77,13 +77,22 @@ namespace osu.Game.Online } /// - /// Perform the polling in this method. Call when done. + /// Performs a poll. Implement but do not call this. /// protected virtual Task Poll() { return Task.CompletedTask; } + /// + /// Immediately performs a . + /// + public void PollImmediately() + { + lastTimePolled = Time.Current - timeBetweenPolls; + scheduleNextPoll(); + } + /// /// Call when a poll operation has completed. /// From 36f6b4fc3fe530adf191f8b3239d1b961fe2dcc7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 18:02:05 +0900 Subject: [PATCH 186/355] Hook up participated filter Very early stages, implementation will change. --- .../Multi/Lounge/Components/RoomsContainer.cs | 1 + osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 6 +++- osu.Game/Screens/Multi/RoomManager.cs | 36 ++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index af66f5bfe8..71d39cd270 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -79,6 +79,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components r.MatchingFilter = matchingFilter; } }); + currentFilter = criteria; } diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 81a478b778..408c02f805 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -120,7 +120,11 @@ namespace osu.Game.Screens.Multi.Lounge Filter.Search.HoldFocus = false; } - private void filterRooms() => rooms.Filter(Filter.CreateCriteria()); + private void filterRooms() + { + rooms.Filter(Filter.CreateCriteria()); + manager.Filter(Filter.CreateCriteria()); + } public void Open(Room room) { diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 7e29aacaf4..7d3e4f5657 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -15,6 +15,7 @@ using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; +using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Screens.Multi { @@ -25,6 +26,8 @@ namespace osu.Game.Screens.Multi public readonly Bindable Current = new Bindable(); + private FilterCriteria currentFilter = new FilterCriteria(); + [Resolved] private APIAccess api { get; set; } @@ -50,6 +53,12 @@ namespace osu.Game.Screens.Multi api.Queue(req); } + public void Filter(FilterCriteria criteria) + { + currentFilter = criteria; + PollImmediately(); + } + protected override Task Poll() { if (!api.IsLoggedIn) @@ -57,10 +66,18 @@ namespace osu.Game.Screens.Multi var tcs = new TaskCompletionSource(); - var pollReq = new GetRoomsRequest(); + var pollReq = new GetRoomsRequest(currentFilter.PrimaryFilter); pollReq.Success += result => { + // Remove past matches + foreach (var r in rooms.ToList()) + { + if (result.All(e => e.RoomID.Value != r.RoomID.Value)) + rooms.Remove(r); + } + + // Add new matches, or update existing foreach (var r in result) { processPlaylist(r); @@ -126,6 +143,23 @@ namespace osu.Game.Screens.Multi private class GetRoomsRequest : APIRequest> { + private readonly PrimaryFilter primaryFilter; + + public GetRoomsRequest(PrimaryFilter primaryFilter) + { + this.primaryFilter = primaryFilter; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + if (primaryFilter == PrimaryFilter.Participated) + req.AddParameter("participated", "1"); + + return req; + } + protected override string Target => "rooms"; } } From 8d458b0b6e6d5d57047834bfcb06c5576efe7566 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Dec 2018 19:45:50 +0900 Subject: [PATCH 187/355] Update framework version --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 305c9035b5..8ae644c06a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 03546c9d0d25ceb6d450ce289d96a4376288a1ea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 15:16:46 +0900 Subject: [PATCH 188/355] Implement primary filter routes --- .../Multi/Lounge/Components/FilterControl.cs | 5 ++-- osu.Game/Screens/Multi/RoomManager.cs | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 01bc23ba4b..286a4c18b0 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components public class FilterControl : SearchableListFilterControl { protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42"); - protected override PrimaryFilter DefaultTab => PrimaryFilter.Current; + protected override PrimaryFilter DefaultTab => PrimaryFilter.Open; public FilterControl() { @@ -28,10 +28,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components public enum PrimaryFilter { - Current, + Open, [Description("Recently Ended")] RecentlyEnded, Participated, + Owned, } public enum SecondaryFilter diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 7d3e4f5657..8e887e51e1 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -150,17 +150,30 @@ namespace osu.Game.Screens.Multi this.primaryFilter = primaryFilter; } - protected override WebRequest CreateWebRequest() + protected override string Target { - var req = base.CreateWebRequest(); + get + { + string target = "rooms"; - if (primaryFilter == PrimaryFilter.Participated) - req.AddParameter("participated", "1"); + switch (primaryFilter) + { + case PrimaryFilter.Open: + break; + case PrimaryFilter.Owned: + target += "/owned"; + break; + case PrimaryFilter.Participated: + target += "/participated"; + break; + case PrimaryFilter.RecentlyEnded: + target += "/ended"; + break; + } - return req; + return target; + } } - - protected override string Target => "rooms"; } } } From 72016a416b9f5be0ef14a929a39c6bd14d773cb8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 15:17:08 +0900 Subject: [PATCH 189/355] Deselect match if ended --- osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 71d39cd270..bde76a01df 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -99,6 +99,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components toRemove.Action = null; roomFlow.Remove(toRemove); + + if (currentRoom.Value == r) + currentRoom.Value = null; } } From 2e28f378deb2afbb1fa621bc506dedda2947b59f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 15:17:33 +0900 Subject: [PATCH 190/355] Move beatmap + mod info to header --- osu.Game.Tests/Visual/TestCaseMatchHeader.cs | 58 +++++++++++++++++ osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 3 - .../UpdateableBeatmapBackgroundSprite.cs | 2 +- .../Screens/Multi/Components/BeatmapTitle.cs | 2 +- .../Multi/Components/BeatmapTypeInfo.cs | 6 +- .../Screens/Multi/Components/ModeTypeInfo.cs | 4 +- .../Multi/Lounge/Components/DrawableRoom.cs | 13 ++-- .../Multi/Lounge/Components/RoomInspector.cs | 11 ++-- .../Screens/Multi/Match/Components/Header.cs | 64 +++++++++++++------ .../Screens/Multi/Match/Components/Info.cs | 25 -------- .../Multi/Match/Components/MatchTabControl.cs | 8 +-- .../Match/Components/RoomSettingsOverlay.cs | 31 +++++++-- osu.Game/Screens/Multi/Match/MatchScreen.cs | 7 +- 13 files changed, 153 insertions(+), 81 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchHeader.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs new file mode 100644 index 0000000000..8ff16a20b9 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs @@ -0,0 +1,58 @@ +// 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 osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Multi.Match.Components; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMatchHeader : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Header) + }; + + private readonly Bindable beatmap = new Bindable(); + private readonly Bindable type = new Bindable(); + private readonly Bindable> mods = new Bindable>(); + + public TestCaseMatchHeader() + { + var header = new Header(new Room()); + + header.Beatmap.BindTo(beatmap); + header.Type.BindTo(type); + header.Mods.BindTo(mods); + + beatmap.Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = "Title", + Artist = "Artist", + AuthorString = "Author", + }, + Version = "Version", + Ruleset = new OsuRuleset().RulesetInfo + }; + + type.Value = new GameTypeTimeshift(); + mods.Value = new Mod[] + { + new OsuModDoubleTime(), + new OsuModNoFail(), + new OsuModRelax(), + }; + + Child = header; + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 799b5f2526..0d3c769dc5 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -44,13 +44,10 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set type", () => info.Type.Value = new GameTypeTagTeam()); - AddStep(@"change name", () => info.Name.Value = @"Room Name!"); AddStep(@"change availability", () => info.Availability.Value = RoomAvailability.InviteOnly); AddStep(@"change status", () => info.Status.Value = new RoomStatusOpen()); AddStep(@"null beatmap", () => info.Beatmap.Value = null); - AddStep(@"change type", () => info.Type.Value = new GameTypeTeamVersus()); AddStep(@"change beatmap", () => info.Beatmap.Value = new BeatmapInfo { StarDifficulty = 4.2, diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 15b89d27bd..0a9726b121 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.Drawables { public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable { - public readonly Bindable Beatmap = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); [Resolved] private BeatmapManager beatmaps { get; set; } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index e3ef5eb401..02ec598f82 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Multi.Components set { beatmapTitle.TextSize = beatmapDash.TextSize = beatmapArtist.TextSize = value; } } - public readonly Bindable Beatmap = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); public BeatmapTitle() { diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index 2bd7b19a0a..90319de40f 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -17,9 +17,9 @@ namespace osu.Game.Screens.Multi.Components { private readonly OsuSpriteText beatmapAuthor; - public readonly Bindable Beatmap = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); - public readonly Bindable Type = new Bindable(); + public readonly IBindable Type = new Bindable(); public BeatmapTypeInfo() { @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Multi.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - beatmapAuthor.Colour = colours.Gray9; + beatmapAuthor.Colour = colours.GrayC; } } } diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 87d150c5a4..8104244084 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -18,8 +18,8 @@ namespace osu.Game.Screens.Multi.Components private readonly Container rulesetContainer; - public readonly Bindable Beatmap = new Bindable(); - public readonly Bindable Type = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); + public readonly IBindable Type = new Bindable(); public ModeTypeInfo() { diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index adcb088f4e..c1a9dd3b1d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly IBindableCollection playlistBind = new BindableCollection(); private readonly IBindable endDateBind = new Bindable(); - private readonly Bindable beatmap = new Bindable(); + private readonly Bindable beatmap = new Bindable(); private UpdateableBeatmapBackgroundSprite background; private BeatmapTitle beatmapTitle; @@ -243,6 +243,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components endDateBind.BindValueChanged(d => endDate.Date = d, true); + background.Beatmap.BindTo(beatmap); + modeTypeInfo.Beatmap.BindTo(beatmap); + beatmapTitle.Beatmap.BindTo(beatmap); + modeTypeInfo.Type.BindTo(typeBind); participantInfo.Host.BindTo(hostBind); @@ -266,12 +270,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components return; // For now, only the first playlist item is supported - var item = playlistBind.First(); - - beatmap.Value = beatmaps.GetWorkingBeatmap(item.Beatmap); - background.Beatmap.Value = item.Beatmap; - modeTypeInfo.Beatmap.Value = item.Beatmap; - beatmapTitle.Beatmap.Value = item.Beatmap; + beatmap.Value = playlistBind.First().Beatmap; } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 818fd78f32..80adc8787f 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly Bindable> participantsBind = new Bindable>(); private readonly IBindableCollection playlistBind = new BindableCollection(); - private readonly Bindable beatmap = new Bindable(); + private readonly Bindable beatmap = new Bindable(); private OsuColour colours; private Box statusStrip; @@ -190,6 +190,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components beatmapTypeInfo.Type.BindTo(typeBind); + background.Beatmap.BindTo(beatmap); + beatmapTypeInfo.Beatmap.BindTo(beatmap); + Room.BindValueChanged(updateRoom, true); } @@ -244,11 +247,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components return; // For now, only the first playlist item is supported - var item = playlistBind.First(); - - beatmap.Value = beatmaps.GetWorkingBeatmap(item.Beatmap); - background.Beatmap.Value = item.Beatmap; - beatmapTypeInfo.Beatmap.Value = item.Beatmap; + beatmap.Value = playlistBind.First().Beatmap; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 4b831ed3c6..de93e8587f 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.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.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -14,6 +15,10 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Play.HUD; +using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Multi.Match.Components @@ -23,6 +28,8 @@ namespace osu.Game.Screens.Multi.Match.Components public const float HEIGHT = 200; public readonly Bindable Beatmap = new Bindable(); + public readonly IBindable Type = new Bindable(); + public readonly Bindable> Mods = new Bindable>(); private readonly Box tabStrip; @@ -30,25 +37,31 @@ namespace osu.Game.Screens.Multi.Match.Components public Action OnRequestSelectBeatmap; - public Header() + public Header(Room room) { RelativeSizeAxes = Axes.X; Height = HEIGHT; + BeatmapTypeInfo beatmapTypeInfo; BeatmapSelectButton beatmapButton; UpdateableBeatmapBackgroundSprite background; + ModDisplay modDisplay; + Children = new Drawable[] { new Container { RelativeSizeAxes = Axes.Both, Masking = true, - Child = background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Black.Opacity(0.5f)), + Children = new Drawable[] + { + background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.4f), Color4.Black.Opacity(0.6f)), + }, + } }, tabStrip = new Box { @@ -60,9 +73,27 @@ namespace osu.Game.Screens.Multi.Match.Components new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Padding = new MarginPadding + { + Left = SearchableListOverlay.WIDTH_PADDING, + Top = 20 + }, Children = new Drawable[] { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + beatmapTypeInfo = new BeatmapTypeInfo(), + modDisplay = new ModDisplay + { + Scale = new Vector2(0.75f), + DisplayUnrankedText = false + }, + } + }, new Container { Anchor = Anchor.TopRight, @@ -70,13 +101,13 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Y, Width = 200, Padding = new MarginPadding { Vertical = 5 }, - Child = beatmapButton = new BeatmapSelectButton + Child = beatmapButton = new BeatmapSelectButton(room) { RelativeSizeAxes = Axes.Both, Height = 1 }, }, - Tabs = new MatchTabControl + Tabs = new MatchTabControl(room) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -86,6 +117,10 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; + beatmapTypeInfo.Beatmap.BindTo(Beatmap); + beatmapTypeInfo.Type.BindTo(Type); + modDisplay.Current.BindTo(Mods); + beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); background.Beatmap.BindTo(Beatmap); @@ -101,17 +136,10 @@ namespace osu.Game.Screens.Multi.Match.Components { private readonly IBindable roomIDBind = new Bindable(); - [Resolved] - private Room room { get; set; } - - public BeatmapSelectButton() + public BeatmapSelectButton(Room room) { Text = "Select beatmap"; - } - [BackgroundDependencyLoader] - private void load() - { roomIDBind.BindTo(room.RoomID); roomIDBind.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true); } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index f63135fc2d..e972a9b6a4 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.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.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions; @@ -14,9 +13,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Components; -using osu.Game.Screens.Play.HUD; using osuTK; namespace osu.Game.Screens.Multi.Match.Components @@ -33,8 +30,6 @@ namespace osu.Game.Screens.Multi.Match.Components public readonly Bindable Availability = new Bindable(); public readonly Bindable Status = new Bindable(); public readonly Bindable Beatmap = new Bindable(); - public readonly Bindable Type = new Bindable(); - public readonly Bindable> Mods = new Bindable>(); public readonly Bindable EndDate = new Bindable(); public Info(Room room) @@ -44,9 +39,7 @@ namespace osu.Game.Screens.Multi.Match.Components ReadyButton readyButton; ViewBeatmapButton viewBeatmapButton; - BeatmapTypeInfo beatmapTypeInfo; OsuSpriteText name; - ModDisplay modDisplay; EndDateInfo endDate; Children = new Drawable[] @@ -82,20 +75,6 @@ namespace osu.Game.Screens.Multi.Match.Components endDate = new EndDateInfo { TextSize = 14 } } }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - beatmapTypeInfo = new BeatmapTypeInfo(), - modDisplay = new ModDisplay - { - Scale = new Vector2(0.75f), - DisplayUnrankedText = false - }, - } - } }, }, new FillFlowContainer @@ -119,10 +98,6 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - beatmapTypeInfo.Beatmap.BindTo(Beatmap); - beatmapTypeInfo.Type.BindTo(Type); - modDisplay.Current.BindTo(Mods); - viewBeatmapButton.Beatmap.BindTo(Beatmap); readyButton.Beatmap.BindTo(Beatmap); diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs index 538dcc341e..a9932ee3c6 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -16,11 +16,10 @@ namespace osu.Game.Screens.Multi.Match.Components { private readonly IBindable roomIdBind = new Bindable(); - [Resolved] - private Room room { get; set; } - - public MatchTabControl() + public MatchTabControl(Room room) { + roomIdBind.BindTo(room.RoomID); + AddItem(new RoomMatchPage()); AddItem(new SettingsMatchPage()); } @@ -28,7 +27,6 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - roomIdBind.BindTo(room.RoomID); roomIdBind.BindValueChanged(v => { if (v.HasValue) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index d3098efb82..bab44d62b2 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -5,6 +5,7 @@ using System; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -133,6 +134,7 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.X, Items = new[] { + TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(30), TimeSpan.FromHours(1), TimeSpan.FromHours(2), @@ -159,14 +161,29 @@ namespace osu.Game.Screens.Multi.Match.Components }, }, }, - ApplyButton = new CreateRoomButton + new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Size = new Vector2(230, 35), - Margin = new MarginPadding { Bottom = 20 }, - Action = apply, - }, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Y = 2, + RelativeSizeAxes = Axes.X, + Height = 60, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), + }, + ApplyButton = new CreateRoomButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(230, 35), + Action = apply, + }, + } + } }, }; diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index c169a5fb5d..656402d0f3 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Multi.Match RelativeSizeAxes = Axes.Both, Content = new[] { - new Drawable[] { header = new Components.Header { Depth = -1 } }, + new Drawable[] { header = new Components.Header(room) { Depth = -1 } }, new Drawable[] { info = new Info(room) { OnStart = onStart } }, new Drawable[] { @@ -135,9 +135,10 @@ namespace osu.Game.Screens.Multi.Match info.Name.BindTo(nameBind); info.Status.BindTo(statusBind); info.Availability.BindTo(availabilityBind); - info.Type.BindTo(typeBind); info.EndDate.BindTo(endDateBind); + header.Type.BindTo(typeBind); + participants.Users.BindTo(participantsBind); participants.MaxParticipants.BindTo(maxParticipantsBind); @@ -167,8 +168,8 @@ namespace osu.Game.Screens.Multi.Match var item = playlistBind.First(); header.Beatmap.Value = item.Beatmap; + header.Mods.Value = item.RequiredMods; info.Beatmap.Value = item.Beatmap; - info.Mods.Value = item.RequiredMods; // Todo: item.Beatmap can be null here... var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; From 07f8b8e334d398de787475881cf34b698c7ba879 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 15:47:26 +0900 Subject: [PATCH 191/355] Update resources --- osu-resources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-resources b/osu-resources index 694cb03f19..9880089b4e 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 694cb03f19c93106ed0f2593f3e506e835fb652a +Subproject commit 9880089b4e8fcd78d68f30c8a40d43bf8dccca86 From bb850da2002a9322437fbd209bd139f0e0435bd2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 15:48:45 +0900 Subject: [PATCH 192/355] Remove skinnability for now Not sure if we want this going forward. --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 4078dce643..ec2839b4ad 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -235,15 +234,12 @@ namespace osu.Game.Rulesets.Osu.Mods /// public void AnimateClosedness(float value) => this.TransformTo(nameof(easing), value, 200, Easing.OutQuint); - public class ModBlindsPanel : CompositeDrawable + public class ModBlindsPanel : Sprite { [BackgroundDependencyLoader] private void load(TextureStore textures) { - InternalChild = new SkinnableDrawable("Play/osu/blinds-panel", s => new Sprite { Texture = textures.Get("Play/osu/blinds-panel") }) - { - RelativeSizeAxes = Axes.Both, - }; + Texture = textures.Get("Play/osu/blinds-panel"); } } } From 3a13899ce1d48881cc60035d31a8a9fba20e0b1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 16:50:38 +0900 Subject: [PATCH 193/355] Add stand-alone chat component --- .../Visual/TestCaseMatchChatDisplay.cs | 83 +++++++++ osu.Game/Online/Chat/StandAloneChatDisplay.cs | 175 ++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs create mode 100644 osu.Game/Online/Chat/StandAloneChatDisplay.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs b/osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs new file mode 100644 index 0000000000..c959eeb3d4 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs @@ -0,0 +1,83 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Online.Chat; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseStandAloneChatDisplay : OsuTestCase + { + private readonly Channel testChannel = new Channel(); + + private readonly User admin = new User + { + Username = "HappyStick", + Id = 2, + Colour = "f2ca34" + }; + + private readonly User redUser = new User + { + Username = "BanchoBot", + Id = 3, + }; + + private readonly User blueUser = new User + { + Username = "Zallius", + Id = 4, + }; + + public TestCaseStandAloneChatDisplay() + { + StandAloneChatDisplay chatDisplay; + + Add(chatDisplay = new StandAloneChatDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(400, 80) + }); + + chatDisplay.Channel.Value = testChannel; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = admin, + Content = "I am a wang!" + })); + + AddStep("message from team red", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = redUser, + Content = "I am team red." + })); + + AddStep("message from team red", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = redUser, + Content = "I plan to win!" + })); + + AddStep("message from team blue", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = blueUser, + Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand." + })); + + AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage + { + Sender = admin, + Content = "Okay okay, calm down guys. Let's do this!" + })); + } + } +} diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs new file mode 100644 index 0000000000..30a730c5a1 --- /dev/null +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -0,0 +1,175 @@ +// 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.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Online.Chat +{ + /// + /// Display a chat channel in an insolated region. + /// + public class StandAloneChatDisplay : CompositeDrawable + { + public readonly Bindable Channel = new Bindable(); + private readonly FillFlowContainer messagesFlow; + private Channel lastChannel; + + public StandAloneChatDisplay() + { + CornerRadius = 10; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.Black, + Alpha = 0.8f, + RelativeSizeAxes = Axes.Both + }, + messagesFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + LayoutEasing = Easing.Out, + LayoutDuration = 500, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Direction = FillDirection.Vertical + } + }; + + Channel.BindValueChanged(channelChanged); + } + + public void Contract() + { + this.FadeIn(300); + this.MoveToY(0, 500, Easing.OutQuint); + } + + public void Expand() + { + this.FadeOut(200); + this.MoveToY(100, 500, Easing.In); + } + + protected virtual Drawable CreateMessage(Message message) + { + return new StandAloneMessage(message); + } + + private void channelChanged(Channel channel) + { + if (lastChannel != null) + lastChannel.NewMessagesArrived -= newMessages; + + lastChannel = channel; + messagesFlow.Clear(); + + if (channel == null) return; + + channel.NewMessagesArrived += newMessages; + } + + private void newMessages(IEnumerable messages) + { + var excessChildren = messagesFlow.Children.Count - 10; + if (excessChildren > 0) + foreach (var c in messagesFlow.Children.Take(excessChildren)) + c.Expire(); + + foreach (var message in messages) + { + var formatted = MessageFormatter.FormatMessage(message); + var drawable = CreateMessage(formatted); + drawable.Y = messagesFlow.Height; + messagesFlow.Add(drawable); + } + } + + protected class StandAloneMessage : CompositeDrawable + { + protected readonly Message Message; + protected OsuSpriteText SenderText; + protected Circle ColourBox; + + public StandAloneMessage(Message message) + { + Message = message; + } + + [BackgroundDependencyLoader] + private void load() + { + Margin = new MarginPadding(3); + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Width = 0.2f, + Children = new Drawable[] + { + SenderText = new OsuSpriteText + { + Font = @"Exo2.0-Bold", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Text = Message.Sender.ToString() + } + } + }, + new Container + { + Size = new Vector2(8, OsuSpriteText.FONT_SIZE), + Margin = new MarginPadding { Horizontal = 3 }, + Children = new Drawable[] + { + ColourBox = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(8) + } + } + }, + new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.5f, + Text = Message.DisplayContent + } + } + } + }; + + if (!string.IsNullOrEmpty(Message.Sender.Colour)) + SenderText.Colour = ColourBox.Colour = OsuColour.FromHex(Message.Sender.Colour); + } + } + } +} From 65447d6f4afcab996dabc0acf74856acbfa0c6f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 17:01:08 +0900 Subject: [PATCH 194/355] Add optional parameters to target messages at a specific channel --- osu.Game/Online/Chat/ChannelManager.cs | 44 +++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index a63af0f7a3..4241b47cd3 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -96,12 +96,14 @@ namespace osu.Game.Online.Chat /// /// The message text that is going to be posted /// Is true if the message is an action, e.g.: user is currently eating - public void PostMessage(string text, bool isAction = false) + /// An optional target channel. If null, will be used. + public void PostMessage(string text, bool isAction = false, Channel target = null) { - if (CurrentChannel.Value == null) - return; + if (target == null) + target = CurrentChannel.Value; - var currentChannel = CurrentChannel.Value; + if (target == null) + return; void dequeueAndRun() { @@ -113,7 +115,7 @@ namespace osu.Game.Online.Chat { if (!api.IsLoggedIn) { - currentChannel.AddNewMessages(new ErrorMessage("Please sign in to participate in chat!")); + target.AddNewMessages(new ErrorMessage("Please sign in to participate in chat!")); return; } @@ -121,29 +123,29 @@ namespace osu.Game.Online.Chat { Sender = api.LocalUser.Value, Timestamp = DateTimeOffset.Now, - ChannelId = CurrentChannel.Value.Id, + ChannelId = target.Id, IsAction = isAction, Content = text }; - currentChannel.AddLocalEcho(message); + target.AddLocalEcho(message); // if this is a PM and the first message, we need to do a special request to create the PM channel - if (currentChannel.Type == ChannelType.PM && !currentChannel.Joined) + if (target.Type == ChannelType.PM && !target.Joined) { - var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(currentChannel.Users.First(), message); + var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message); createNewPrivateMessageRequest.Success += createRes => { - currentChannel.Id = createRes.ChannelID; - currentChannel.ReplaceMessage(message, createRes.Message); + target.Id = createRes.ChannelID; + target.ReplaceMessage(message, createRes.Message); dequeueAndRun(); }; createNewPrivateMessageRequest.Failure += exception => { Logger.Error(exception, "Posting message failed."); - currentChannel.ReplaceMessage(message, null); + target.ReplaceMessage(message, null); dequeueAndRun(); }; @@ -155,14 +157,14 @@ namespace osu.Game.Online.Chat req.Success += m => { - currentChannel.ReplaceMessage(message, m); + target.ReplaceMessage(message, m); dequeueAndRun(); }; req.Failure += exception => { Logger.Error(exception, "Posting message failed."); - currentChannel.ReplaceMessage(message, null); + target.ReplaceMessage(message, null); dequeueAndRun(); }; @@ -178,9 +180,13 @@ namespace osu.Game.Online.Chat /// Posts a command locally. Commands like /help will result in a help message written in the current channel. /// /// the text containing the command identifier and command parameters. - public void PostCommand(string text) + /// An optional target channel. If null, will be used. + public void PostCommand(string text, Channel target = null) { - if (CurrentChannel.Value == null) + if (target == null) + target = CurrentChannel.Value; + + if (target == null) return; var parameters = text.Split(new[] { ' ' }, 2); @@ -192,7 +198,7 @@ namespace osu.Game.Online.Chat case "me": if (string.IsNullOrWhiteSpace(content)) { - CurrentChannel.Value.AddNewMessages(new ErrorMessage("Usage: /me [action]")); + target.AddNewMessages(new ErrorMessage("Usage: /me [action]")); break; } @@ -200,11 +206,11 @@ namespace osu.Game.Online.Chat break; case "help": - CurrentChannel.Value.AddNewMessages(new InfoMessage("Supported commands: /help, /me [action]")); + target.AddNewMessages(new InfoMessage("Supported commands: /help, /me [action]")); break; default: - CurrentChannel.Value.AddNewMessages(new ErrorMessage($@"""/{command}"" is not supported! For a list of supported commands see /help")); + target.AddNewMessages(new ErrorMessage($@"""/{command}"" is not supported! For a list of supported commands see /help")); break; } } From 1701af61d64ad2d16f51ad67e38ad402b0c49c7b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 17:33:55 +0900 Subject: [PATCH 195/355] Add host avatar+username to match screen --- .../Visual/TestCaseMatchHostInfo.cs | 29 ++++++++++ .../Screens/Multi/Match/Components/Header.cs | 7 +-- .../Multi/Match/Components/HostInfo.cs | 54 +++++++++++++++++++ .../Screens/Multi/Match/Components/Info.cs | 1 + 4 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/HostInfo.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs new file mode 100644 index 0000000000..006af2e10e --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchHostInfo.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; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMatchHostInfo : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HostInfo) + }; + + public TestCaseMatchHostInfo() + { + Child = new HostInfo(new Room { Host = { Value = new User { Username = "ImAHost" }}}) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + } + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index de93e8587f..3f4f137413 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -73,16 +73,13 @@ namespace osu.Game.Screens.Multi.Match.Components new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Left = SearchableListOverlay.WIDTH_PADDING, - Top = 20 - }, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, Children = new Drawable[] { new FillFlowContainer { AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 20 }, Direction = FillDirection.Vertical, Children = new Drawable[] { diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs new file mode 100644 index 0000000000..e77f534a17 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; +using osu.Game.Online.Multiplayer; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class HostInfo : CompositeDrawable + { + public HostInfo(Room room) + { + AutoSizeAxes = Axes.X; + Height = 50; + + LinkFlowContainer linkContainer; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new UpdateableAvatar + { + Size = new Vector2(50), + User = room.Host.Value + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + linkContainer = new LinkFlowContainer { AutoSizeAxes = Axes.Both } + } + } + } + }; + + linkContainer.AddText("hosted by"); + linkContainer.NewLine(); + linkContainer.AddLink(room.Host.Value.Username,null, LinkAction.OpenUserProfile, room.Host.Value.Id.ToString(), "Open profile", s => s.Font = "Exo2.0-BoldItalic"); + } + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index e972a9b6a4..de02899a01 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -75,6 +75,7 @@ namespace osu.Game.Screens.Multi.Match.Components endDate = new EndDateInfo { TextSize = 14 } } }, + new HostInfo(room), }, }, new FillFlowContainer From 8db3ac0a9f209102f3af081a5c025f773fc72e81 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 18:04:35 +0900 Subject: [PATCH 196/355] Make user links clickable --- .../Lounge/Components/ParticipantInfo.cs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 3bc20b58c5..042dd96b61 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -9,7 +9,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; @@ -17,7 +19,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class ParticipantInfo : Container { - private readonly OsuSpriteText host; private readonly FillFlowContainer levelRangeContainer; public readonly Bindable Host = new Bindable(); @@ -31,6 +32,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components OsuSpriteText levelRangeHigher; OsuSpriteText levelRangeLower; Container flagContainer; + LinkFlowContainer hostText; Children = new Drawable[] { @@ -62,20 +64,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, }, }, - new OsuSpriteText - { - Text = "hosted by", - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - TextSize = 14, - }, - host = new OsuSpriteText + hostText = new LinkFlowContainer { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 14, - Font = @"Exo2.0-BoldItalic", - }, + AutoSizeAxes = Axes.Both + } }, }, levelRangeContainer = new FillFlowContainer @@ -122,7 +116,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components Host.BindValueChanged(v => { - host.Text = v.Username; + hostText.Clear(); + hostText.AddText("hosted by "); + hostText.AddLink(v.Username, null, LinkAction.OpenUserProfile, v.Id.ToString(), "Open profile", s => s.Font = "Exo2.0-BoldItalic"); + flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; }); @@ -138,7 +135,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void load(OsuColour colours) { levelRangeContainer.Colour = colours.Gray9; - host.Colour = colours.Blue; } } } From deaf4ab4a12e5f656e090b5080d35536711532f5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 18:21:55 +0900 Subject: [PATCH 197/355] Cleanup --- osu.Game/Screens/Multi/Match/Components/HostInfo.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index e77f534a17..830d720bd4 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -38,10 +38,7 @@ namespace osu.Game.Screens.Multi.Match.Components Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, - Children = new Drawable[] - { - linkContainer = new LinkFlowContainer { AutoSizeAxes = Axes.Both } - } + Child = linkContainer = new LinkFlowContainer { AutoSizeAxes = Axes.Both } } } }; From bc8b0485d8cf58772d76aae94060baaded4a9430 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 18:21:37 +0900 Subject: [PATCH 198/355] Add textbox/posting support --- ...ay.cs => TestCaseStandAloneChatDisplay.cs} | 27 ++++++++-- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 54 ++++++++++++++++++- 2 files changed, 76 insertions(+), 5 deletions(-) rename osu.Game.Tests/Visual/{TestCaseMatchChatDisplay.cs => TestCaseStandAloneChatDisplay.cs} (73%) diff --git a/osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs b/osu.Game.Tests/Visual/TestCaseStandAloneChatDisplay.cs similarity index 73% rename from osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs rename to osu.Game.Tests/Visual/TestCaseStandAloneChatDisplay.cs index c959eeb3d4..16ce720ab1 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchChatDisplay.cs +++ b/osu.Game.Tests/Visual/TestCaseStandAloneChatDisplay.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.Allocation; using osu.Framework.Graphics; using osu.Game.Online.Chat; using osu.Game.Users; @@ -31,24 +32,42 @@ namespace osu.Game.Tests.Visual Id = 4, }; + [Cached] + private ChannelManager channelManager = new ChannelManager(); + + private readonly StandAloneChatDisplay chatDisplay; + private readonly StandAloneChatDisplay chatDisplay2; + public TestCaseStandAloneChatDisplay() { - StandAloneChatDisplay chatDisplay; + Add(channelManager); Add(chatDisplay = new StandAloneChatDisplay { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding(20), Size = new Vector2(400, 80) }); - chatDisplay.Channel.Value = testChannel; + Add(chatDisplay2 = new StandAloneChatDisplay(true) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Margin = new MarginPadding(20), + Size = new Vector2(400, 150) + }); } protected override void LoadComplete() { base.LoadComplete(); + channelManager.CurrentChannel.Value = testChannel; + + chatDisplay.Channel.Value = testChannel; + chatDisplay2.Channel.Value = testChannel; + AddStep("message from admin", () => testChannel.AddLocalEcho(new LocalEchoMessage { Sender = admin, diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 30a730c5a1..cb4bf9fdf8 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -8,9 +8,11 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; @@ -22,10 +24,20 @@ namespace osu.Game.Online.Chat public class StandAloneChatDisplay : CompositeDrawable { public readonly Bindable Channel = new Bindable(); + private readonly FillFlowContainer messagesFlow; + private Channel lastChannel; - public StandAloneChatDisplay() + private readonly FocusedTextBox textbox; + + protected ChannelManager ChannelManager; + + /// + /// Construct a new instance. + /// + /// Whether a textbox for posting new messages should be displayed. + public StandAloneChatDisplay(bool postingTextbox = false) { CornerRadius = 10; Masking = true; @@ -50,9 +62,49 @@ namespace osu.Game.Online.Chat } }; + const float textbox_height = 30; + + if (postingTextbox) + { + messagesFlow.Y -= textbox_height; + AddInternal(textbox = new FocusedTextBox + { + RelativeSizeAxes = Axes.X, + Height = textbox_height, + PlaceholderText = "type your message", + OnCommit = postMessage, + ReleaseFocusOnCommit = false, + HoldFocus = true, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }); + } + Channel.BindValueChanged(channelChanged); } + [BackgroundDependencyLoader(true)] + private void load(ChannelManager manager) + { + if (ChannelManager == null) + ChannelManager = manager; + } + + private void postMessage(TextBox sender, bool newtext) + { + var text = textbox.Text.Trim(); + + if (string.IsNullOrWhiteSpace(text)) + return; + + if (text[0] == '/') + ChannelManager?.PostCommand(text.Substring(1)); + else + ChannelManager?.PostMessage(text); + + textbox.Text = string.Empty; + } + public void Contract() { this.FadeIn(300); From d3368df94dd3338cbe611304185a773b89bf7df6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 19:35:32 +0900 Subject: [PATCH 199/355] Simplify changes to RulesetContainer --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 +-- osu.Game/Rulesets/UI/RulesetContainer.cs | 35 ++++++++++------------ osu.Game/Screens/Play/Player.cs | 1 - 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index ec2839b4ad..f6c2c1215d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - bool hasEasy = rulesetContainer.ActiveMods.Any(m => m is ModEasy); - bool hasHardrock = rulesetContainer.ActiveMods.Any(m => m is ModHardRock); + bool hasEasy = rulesetContainer.Mods.Any(m => m is ModEasy); + bool hasHardrock = rulesetContainer.Mods.Any(m => m is ModHardRock); rulesetContainer.Overlays.Add(blinds = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, hasEasy, hasHardrock, rulesetContainer.Beatmap)); } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 67bcb7581f..22d4eee5e4 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.UI /// /// Place to put drawables above hit objects but below UI. /// - public readonly Container Overlays; + public Container Overlays { get; protected set; } /// /// The cursor provided by this . May be null if no cursor is provided. @@ -92,12 +92,6 @@ namespace osu.Game.Rulesets.UI { Ruleset = ruleset; playfield = new Lazy(CreatePlayfield); - Overlays = new Container - { - RelativeSizeAxes = Axes.Both, - Width = 1, - Height = 1 - }; IsPaused.ValueChanged += paused => { @@ -215,7 +209,7 @@ namespace osu.Game.Rulesets.UI /// /// The mods which are to be applied. /// - protected IEnumerable Mods; + public IEnumerable Mods { get; protected set; } /// /// The this was created with. @@ -226,7 +220,6 @@ namespace osu.Game.Rulesets.UI protected override Container Content => content; private Container content; - private IEnumerable mods; /// /// Whether to assume the beatmap passed into this is for the current ruleset. @@ -256,17 +249,24 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - KeyBindingInputManager.Add(content = new Container + KeyBindingInputManager.Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - }); - - AddInternal(KeyBindingInputManager); - KeyBindingInputManager.Add(Playfield); + content = new Container + { + RelativeSizeAxes = Axes.Both, + }, + Playfield + }; if (Cursor != null) KeyBindingInputManager.Add(Cursor); + InternalChildren = new Drawable[] + { + KeyBindingInputManager, + Overlays = new Container { RelativeSizeAxes = Axes.Both } + }; + // Apply mods applyRulesetMods(Mods, config); @@ -324,11 +324,6 @@ namespace osu.Game.Rulesets.UI mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); } - /// - /// Returns the currently selected mods for this ruleset container. - /// - public IEnumerable ActiveMods { get => Mods; } - /// /// Creates and adds the visual representation of a to this . /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fd2c94e814..19b49b099c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -184,7 +184,6 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Child = RulesetContainer }, - RulesetContainer.Overlays, new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, From ef9d93ff6b93ec3eacd500e509728f2f9ca04eea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 19:46:39 +0900 Subject: [PATCH 200/355] Remove mod multipliers We decided that mods shouldn't be interacting with other mods. This can be added once we have the ability to have per-mod settings, as a difficulty setting local to blinds. --- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 71 +++------------------- osu.Game/Rulesets/UI/RulesetContainer.cs | 2 +- 2 files changed, 10 insertions(+), 63 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index f6c2c1215d..cc2102f0e9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,10 +34,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - bool hasEasy = rulesetContainer.Mods.Any(m => m is ModEasy); - bool hasHardrock = rulesetContainer.Mods.Any(m => m is ModHardRock); - - rulesetContainer.Overlays.Add(blinds = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, hasEasy, hasHardrock, rulesetContainer.Beatmap)); + rulesetContainer.Overlays.Add(blinds = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, rulesetContainer.Beatmap)); } public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -69,12 +65,7 @@ namespace osu.Game.Rulesets.Osu.Mods private readonly float targetBreakMultiplier = 0; private readonly float easing = 1; - private const float black_depth = 10; - private const float bg_panel_depth = 8; - private const float fg_panel_depth = 4; - private readonly CompositeDrawable restrictTo; - private readonly bool modEasy, modHardrock; /// /// @@ -89,13 +80,10 @@ namespace osu.Game.Rulesets.Osu.Mods /// private const float leniency = 0.1f; - public DrawableOsuBlinds(CompositeDrawable restrictTo, bool hasEasy, bool hasHardrock, Beatmap beatmap) + public DrawableOsuBlinds(CompositeDrawable restrictTo, Beatmap beatmap) { this.restrictTo = restrictTo; this.beatmap = beatmap; - - modEasy = hasEasy; - modHardrock = hasHardrock; } [BackgroundDependencyLoader] @@ -111,9 +99,6 @@ namespace osu.Game.Rulesets.Osu.Mods Origin = Anchor.TopLeft, Colour = Color4.Black, RelativeSizeAxes = Axes.Y, - Width = 0, - Height = 1, - Depth = black_depth }, blackBoxRight = new Box { @@ -121,60 +106,22 @@ namespace osu.Game.Rulesets.Osu.Mods Origin = Anchor.TopRight, Colour = Color4.Black, RelativeSizeAxes = Axes.Y, - Width = 0, - Height = 1, - Depth = black_depth }, bgPanelLeft = new ModBlindsPanel { Origin = Anchor.TopRight, Colour = Color4.Gray, - Depth = bg_panel_depth + 1 - }, - panelLeft = new ModBlindsPanel - { - Origin = Anchor.TopRight, - Depth = bg_panel_depth - }, - bgPanelRight = new ModBlindsPanel - { - Origin = Anchor.TopLeft, - Colour = Color4.Gray, - Depth = fg_panel_depth + 1 - }, - panelRight = new ModBlindsPanel - { - Origin = Anchor.TopLeft, - Depth = fg_panel_depth }, + panelLeft = new ModBlindsPanel { Origin = Anchor.TopRight, }, + bgPanelRight = new ModBlindsPanel { Colour = Color4.Gray }, + panelRight = new ModBlindsPanel() }; } - private float applyGap(float value) - { - const float easy_multiplier = 0.95f; - const float hardrock_multiplier = 1.1f; + private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; - float multiplier = 1; - if (modEasy) - { - multiplier = easy_multiplier; - // TODO: include OD/CS - } - else if (modHardrock) - { - multiplier = hardrock_multiplier; - // TODO: include OD/CS - } - - return MathHelper.Clamp(value * multiplier, 0, target_clamp) * targetBreakMultiplier; - } - - private static float applyAdjustmentCurve(float value) - { - // lagrange polinominal for (0,0) (0.5,0.35) (1,1) should make a good curve - return 0.6f * value * value + 0.4f * value; - } + // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve + private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; protected override void Update() { @@ -186,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Mods start -= rawWidth * leniency * 0.5f; end += rawWidth * leniency * 0.5f; - float width = (end - start) * 0.5f * applyAdjustmentCurve(applyGap(easing)); + float width = (end - start) * 0.5f * applyAdjustmentCurve(calculateGap(easing)); // different values in case the playfield ever moves from center to somewhere else. blackBoxLeft.Width = start + width; diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 22d4eee5e4..56222ff282 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.UI /// /// The mods which are to be applied. /// - public IEnumerable Mods { get; protected set; } + protected IEnumerable Mods; /// /// The this was created with. From 36f57a7abbd4155a31c3db8f4d2b4d03b5cea7ce Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Thu, 20 Dec 2018 05:49:05 -0500 Subject: [PATCH 201/355] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index baaba22726..a2f6472371 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ We are accepting bug reports (please report with as much detail as possible). Fe # Requirements -- A desktop platform with the [.NET Core SDK 2.1](https://www.microsoft.com/net/learn/get-started) or higher installed. +- A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed. - When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio Community Edition](https://www.visualstudio.com/) (Windows), [Visual Studio Code](https://code.visualstudio.com/) (with the C# plugin installed) or [Jetbrains Rider](https://www.jetbrains.com/rider/) (commercial). # Building and running From f8d25a1b6ca15d598284a5323e5ff4867db40ae2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 20:01:58 +0900 Subject: [PATCH 202/355] Add method to add arbitrary drawables as links --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 795fe7caf4..ce1e583c6f 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; +using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -61,8 +62,19 @@ namespace osu.Game.Graphics.Containers } public void AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); + + public void AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) { - AddInternal(new DrawableLinkCompiler(AddText(text, creationParameters).OfType().ToList()) + foreach (var t in text) + AddArbitraryDrawable(t); + + createLink(text, null, url, linkType, linkArgument, tooltipText); + } + + private void createLink(IEnumerable drawables, string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + { + AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { TooltipText = tooltipText ?? (url != text ? url : string.Empty), Action = () => From 6a76e335c726b5d4753d4fb250dc0b6e22073167 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 20:03:39 +0900 Subject: [PATCH 203/355] Linkify everything --- .../Screens/Multi/Components/BeatmapTitle.cs | 56 ++++++++++++------- .../Multi/Components/BeatmapTypeInfo.cs | 26 +++++---- .../Multi/Lounge/Components/DrawableRoom.cs | 1 - .../Multi/Match/Components/HostInfo.cs | 2 +- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index 02ec598f82..67d414a080 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -6,36 +6,38 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; namespace osu.Game.Screens.Multi.Components { public class BeatmapTitle : CompositeDrawable { - private readonly OsuSpriteText beatmapTitle, beatmapDash, beatmapArtist; + private float textSize = OsuSpriteText.FONT_SIZE; public float TextSize { - set { beatmapTitle.TextSize = beatmapDash.TextSize = beatmapArtist.TextSize = value; } + get => textSize; + set + { + if (textSize == value) + return; + textSize = value; + + updateText(); + } } public readonly IBindable Beatmap = new Bindable(); + private readonly LinkFlowContainer textFlow; + public BeatmapTitle() { AutoSizeAxes = Axes.Both; - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - beatmapTitle = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, - beatmapDash = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", }, - beatmapArtist = new OsuSpriteText { Font = @"Exo2.0-RegularItalic", }, - } - }; + InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both }; Beatmap.BindValueChanged(v => updateText()); } @@ -51,16 +53,30 @@ namespace osu.Game.Screens.Multi.Components if (!IsLoaded) return; + textFlow.Clear(); + if (Beatmap.Value == null) - { - beatmapTitle.Text = "Changing map"; - beatmapDash.Text = beatmapArtist.Text = string.Empty; - } + textFlow.AddText("Changing map", s => s.TextSize = TextSize); else { - beatmapTitle.Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)); - beatmapDash.Text = @" - "; - beatmapArtist.Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)); + textFlow.AddLink(new[] + { + new OsuSpriteText + { + Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)), + TextSize = TextSize, + }, + new OsuSpriteText + { + Text = " - ", + TextSize = TextSize, + }, + new OsuSpriteText + { + Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)), + TextSize = TextSize, + } + }, null, LinkAction.OpenBeatmap, Beatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap"); } } } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index 90319de40f..a06eaa35dc 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -1,13 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; using osu.Game.Online.Multiplayer; using osuTK; @@ -15,8 +15,6 @@ namespace osu.Game.Screens.Multi.Components { public class BeatmapTypeInfo : CompositeDrawable { - private readonly OsuSpriteText beatmapAuthor; - public readonly IBindable Beatmap = new Bindable(); public readonly IBindable Type = new Bindable(); @@ -27,6 +25,7 @@ namespace osu.Game.Screens.Multi.Components BeatmapTitle beatmapTitle; ModeTypeInfo modeTypeInfo; + LinkFlowContainer beatmapAuthor; InternalChild = new FillFlowContainer { @@ -45,11 +44,11 @@ namespace osu.Game.Screens.Multi.Components Children = new Drawable[] { beatmapTitle = new BeatmapTitle(), - beatmapAuthor = new OsuSpriteText + beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - TextSize = 14, + AutoSizeAxes = Axes.Both }, }, }, @@ -61,13 +60,16 @@ namespace osu.Game.Screens.Multi.Components beatmapTitle.Beatmap.BindTo(Beatmap); - Beatmap.BindValueChanged(v => beatmapAuthor.Text = v == null ? string.Empty : $"mapped by {v.Metadata.Author}"); - } + Beatmap.BindValueChanged(v => + { + beatmapAuthor.Clear(); - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - beatmapAuthor.Colour = colours.GrayC; + if (v != null) + { + beatmapAuthor.AddText("mapped by ", s => s.Colour = OsuColour.Gray(0.8f)); + beatmapAuthor.AddLink(v.Metadata.Author.Username, null, LinkAction.OpenUserProfile, v.Metadata.Author.Id.ToString(), "View Profile"); + } + }); } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index c1a9dd3b1d..f4e304d0a8 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -205,7 +205,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components beatmapTitle = new BeatmapTitle { TextSize = 14, - Colour = colours.Gray9 }, } } diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index 830d720bd4..883f88b056 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Multi.Match.Components linkContainer.AddText("hosted by"); linkContainer.NewLine(); - linkContainer.AddLink(room.Host.Value.Username,null, LinkAction.OpenUserProfile, room.Host.Value.Id.ToString(), "Open profile", s => s.Font = "Exo2.0-BoldItalic"); + linkContainer.AddLink(room.Host.Value.Username, null, LinkAction.OpenUserProfile, room.Host.Value.Id.ToString(), "View Profile", s => s.Font = "Exo2.0-BoldItalic"); } } } From 104a3c8ffcd5ababd52b66e1d0db183b6fa9c417 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 20:08:22 +0900 Subject: [PATCH 204/355] Add click to avatar --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 12 +---- osu.Game/Overlays/Profile/ProfileHeader.cs | 1 + .../Overlays/Toolbar/ToolbarUserButton.cs | 1 + osu.Game/Users/Avatar.cs | 51 +++++++++++++++++-- osu.Game/Users/UpdateableAvatar.cs | 23 ++++++--- osu.Game/Users/UserPanel.cs | 1 + 6 files changed, 67 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index c2f03a4b66..0b260d4f39 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -9,7 +9,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using osu.Framework.Allocation; using osu.Game.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -20,7 +19,6 @@ namespace osu.Game.Overlays.BeatmapSet private const float height = 50; private readonly UpdateableAvatar avatar; - private readonly ClickableArea clickableArea; private readonly FillFlowContainer fields; private BeatmapSetInfo beatmapSet; @@ -73,7 +71,7 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { - clickableArea = new ClickableArea + new Container { AutoSizeAxes = Axes.Both, CornerRadius = 3, @@ -100,14 +98,8 @@ namespace osu.Game.Overlays.BeatmapSet }; } - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay profile) + private void load() { - clickableArea.Action = () => - { - if (avatar.User != null) profile?.ShowUser(avatar.User); - }; - updateDisplay(); } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index a8075ec295..3c7fe0b1eb 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -82,6 +82,7 @@ namespace osu.Game.Overlays.Profile Origin = Anchor.BottomLeft, Masking = true, CornerRadius = 5, + OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 017d748600..36299e51f0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Toolbar Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, CornerRadius = 4, + OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index e6e1ba3c53..24864cce51 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -3,17 +3,29 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; namespace osu.Game.Users { public class Avatar : Container { + /// + /// Whether to open the user's profile when clicked. + /// + public readonly BindableBool OpenOnClick = new BindableBool(true); + private readonly User user; + [Resolved(CanBeNull = true)] + private OsuGame game { get; set; } + /// /// An avatar for specified user. /// @@ -33,14 +45,43 @@ namespace osu.Game.Users if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); if (texture == null) texture = textures.Get(@"Online/avatar-guest"); - Add(new Sprite + ClickableArea clickableArea; + Add(clickableArea = new ClickableArea { RelativeSizeAxes = Axes.Both, - Texture = texture, - FillMode = FillMode.Fit, - Anchor = Anchor.Centre, - Origin = Anchor.Centre + Child = new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = texture, + FillMode = FillMode.Fit, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, + Action = openProfile }); + + clickableArea.Enabled.BindTo(OpenOnClick); + } + + private void openProfile() + { + if (!OpenOnClick) + return; + + if (user != null) + game?.ShowUser(user.Id); + } + + private class ClickableArea : OsuClickableContainer, IHasTooltip + { + public string TooltipText => Enabled.Value ? @"View Profile" : null; + + protected override bool OnClick(ClickEvent e) + { + if (!Enabled) + return false; + return base.OnClick(e); + } } } } diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index 6c0b841abf..a8d9d3d66b 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.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.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,6 +36,11 @@ namespace osu.Game.Users } } + /// + /// Whether to open the user's profile when clicked. + /// + public readonly BindableBool OpenOnClick = new BindableBool(true); + protected override void LoadComplete() { base.LoadComplete(); @@ -45,15 +51,18 @@ namespace osu.Game.Users { displayedAvatar?.FadeOut(300); displayedAvatar?.Expire(); + if (user != null || ShowGuestOnNull) { - Add(displayedAvatar = new DelayedLoadWrapper( - new Avatar(user) - { - RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), - }) - ); + var avatar = new Avatar(user) + { + RelativeSizeAxes = Axes.Both, + OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), + }; + + avatar.OpenOnClick.BindTo(OpenOnClick); + + Add(displayedAvatar = new DelayedLoadWrapper(avatar)); } } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d86f608bd1..1d302ef04f 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -99,6 +99,7 @@ namespace osu.Game.Users User = user, Masking = true, CornerRadius = 5, + OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, From 9031896484d01de2ec4b517f83b53b6539c3d0b1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 20:09:17 +0900 Subject: [PATCH 205/355] Fix create room button showing in song select --- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 4a0fa141c8..0239042241 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Multi createButton.Hide(); } - else + else if (currentScreen is LoungeScreen) createButton.Show(); } From 822225577b8f072501fde2959691f94d98ead5b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 20:58:34 +0900 Subject: [PATCH 206/355] Add joining/parting room requests --- .../Multi/Lounge/Components/RoomInspector.cs | 2 +- .../Multi/Lounge/Components/RoomsContainer.cs | 19 ++--- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 12 +-- osu.Game/Screens/Multi/Match/MatchScreen.cs | 7 +- osu.Game/Screens/Multi/Multiplayer.cs | 5 +- osu.Game/Screens/Multi/RoomManager.cs | 78 ++++++++++++++++++- 6 files changed, 99 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 80adc8787f..f290830334 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { private const float transition_duration = 100; - public readonly Bindable Room = new Bindable(); + public readonly IBindable Room = new Bindable(); private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; private readonly Bindable nameBind = new Bindable(); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index bde76a01df..b17ddca21d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -17,10 +17,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class RoomsContainer : CompositeDrawable, IHasFilterableChildren { - public Action OpenRequested; + public Action JoinRequested; + + private readonly Bindable selectedRoom = new Bindable(); + public IBindable SelectedRoom => selectedRoom; private readonly IBindableCollection rooms = new BindableCollection(); - private readonly Bindable currentRoom = new Bindable(); private readonly FillFlowContainer roomFlow; @@ -44,15 +46,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components [BackgroundDependencyLoader] private void load() { - currentRoom.BindTo(manager.Current); rooms.BindTo(manager.Rooms); rooms.ItemsAdded += addRooms; rooms.ItemsRemoved += removeRooms; addRooms(rooms); - - currentRoom.BindValueChanged(selectRoom, true); } private FilterCriteria currentFilter; @@ -100,8 +99,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components roomFlow.Remove(toRemove); - if (currentRoom.Value == r) - currentRoom.Value = null; + selectRoom(null); } } @@ -110,12 +108,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components var drawable = roomFlow.FirstOrDefault(r => r.Room == room); if (drawable != null && drawable.State == SelectionState.Selected) - OpenRequested?.Invoke(room); + JoinRequested?.Invoke(room); else - { - currentRoom.Value = room; roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected); - } + + selectedRoom.Value = room; } public IEnumerable FilterTerms => Enumerable.Empty(); diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 408c02f805..562dfaa347 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = rooms = new RoomsContainer { OpenRequested = Open } + Child = rooms = new RoomsContainer { JoinRequested = r => manager?.JoinRoom(r) } }, }, inspector = new RoomInspector @@ -68,10 +68,10 @@ namespace osu.Game.Screens.Multi.Lounge }, }, }, - manager = new RoomManager() + manager = new RoomManager { OpenRequested = Open } }; - inspector.Room.BindTo(manager.Current); + inspector.Room.BindTo(rooms.SelectedRoom); Filter.Search.Current.ValueChanged += s => filterRooms(); Filter.Tabs.Current.ValueChanged += t => filterRooms(); @@ -103,15 +103,17 @@ namespace osu.Game.Screens.Multi.Lounge protected override bool OnExiting(Screen next) { + manager?.PartRoom(); + Filter.Search.HoldFocus = false; return base.OnExiting(next); } protected override void OnResuming(Screen last) { - base.OnResuming(last); + manager?.PartRoom(); - Filter.Search.HoldFocus = true; + base.OnResuming(last); } protected override void OnSuspending(Screen next) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 656402d0f3..b33c871fad 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; @@ -52,12 +51,12 @@ namespace osu.Game.Screens.Multi.Match [Resolved] private BeatmapManager beatmapManager { get; set; } - [Resolved] - private APIAccess api { get; set; } - [Resolved] private OsuGame game { get; set; } + [Resolved(CanBeNull = true)] + private RoomManager manager { get; set; } + public MatchScreen(Room room, Action pushGameplayScreen) { this.room = room; diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 0239042241..9339c6693f 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Multi public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; private readonly OsuButton createButton; + private readonly LoungeScreen loungeScreen; private OsuScreen currentScreen; @@ -37,7 +38,6 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both, }; - LoungeScreen loungeScreen; waves.AddRange(new Drawable[] { new Container @@ -102,6 +102,9 @@ namespace osu.Game.Screens.Multi if (track != null) track.Looping = false; + loungeScreen.MakeCurrent(); + loungeScreen.Exit(); + return base.OnExiting(next); } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 8e887e51e1..b3bb9cb147 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.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; using System.Collections.Generic; using System.Linq; using System.Net.Http; @@ -16,15 +17,18 @@ using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Lounge.Components; +using osu.Game.Users; namespace osu.Game.Screens.Multi { public class RoomManager : PollingComponent { + public Action OpenRequested; + public IBindableCollection Rooms => rooms; private readonly BindableCollection rooms = new BindableCollection(); - public readonly Bindable Current = new Bindable(); + private Room currentRoom; private FilterCriteria currentFilter = new FilterCriteria(); @@ -47,12 +51,40 @@ namespace osu.Game.Screens.Multi room.Host.Value = api.LocalUser; var req = new CreateRoomRequest(room); - req.Success += result => addRoom(room, result); req.Failure += exception => Logger.Log($"Failed to create room: {exception}"); + api.Queue(req); } + private JoinRoomRequest currentJoinRoomRequest; + + public void JoinRoom(Room room) + { + currentJoinRoomRequest?.Cancel(); + currentJoinRoomRequest = null; + + currentJoinRoomRequest = new JoinRoomRequest(room, api.LocalUser.Value); + currentJoinRoomRequest.Success += () => + { + currentRoom = room; + OpenRequested?.Invoke(room); + }; + + currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}"); + + api.Queue(currentJoinRoomRequest); + } + + public void PartRoom() + { + if (currentRoom == null) + return; + + api.Queue(new PartRoomRequest(currentRoom, api.LocalUser.Value)); + currentRoom = null; + } + public void Filter(FilterCriteria criteria) { currentFilter = criteria; @@ -141,6 +173,48 @@ namespace osu.Game.Screens.Multi protected override string Target => "rooms"; } + private class JoinRoomRequest : APIRequest + { + private readonly Room room; + private readonly User user; + + public JoinRoomRequest(Room room, User user) + { + this.room = room; + this.user = user; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Put; + return req; + } + + protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; + } + + private class PartRoomRequest : APIRequest + { + private readonly Room room; + private readonly User user; + + public PartRoomRequest(Room room, User user) + { + this.room = room; + this.user = user; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Delete; + return req; + } + + protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; + } + private class GetRoomsRequest : APIRequest> { private readonly PrimaryFilter primaryFilter; From aaac45ab8cb384402c068dcc2226121fdf0affbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Dec 2018 21:06:40 +0900 Subject: [PATCH 207/355] Add ability to select chat tabs with alt-1-9 --- osu.Game/Graphics/UserInterface/Nub.cs | 16 ++++++++++- osu.Game/Overlays/ChatOverlay.cs | 37 ++++++++++++++++++++++++- osu.Game/Overlays/Volume/MuteButton.cs | 16 ++++++++++- osu.Game/Screens/Play/HUD/ModDisplay.cs | 24 ++++++++++++---- 4 files changed, 84 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 974708af97..b715c80fb6 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.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; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -99,7 +100,20 @@ namespace osu.Game.Graphics.UserInterface } } - public Bindable Current { get; } = new Bindable(); + private readonly Bindable current = new Bindable(); + + public Bindable Current + { + get => current; + set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + current.UnbindBindings(); + current.BindTo(value); + } + } private Color4 accentColour; public Color4 AccentColour diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 75e22f85d1..680e7ac416 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -19,6 +20,7 @@ using osu.Game.Online.Chat; using osu.Game.Overlays.Chat; using osu.Game.Overlays.Chat.Selection; using osu.Game.Overlays.Chat.Tabs; +using osuTK.Input; namespace osu.Game.Overlays { @@ -222,7 +224,7 @@ namespace osu.Game.Overlays else { currentChannelContainer.Clear(false); - Scheduler.Add(() => currentChannelContainer.Add(loaded)); + currentChannelContainer.Add(loaded); } } @@ -262,6 +264,39 @@ namespace osu.Game.Overlays return base.OnDragEnd(e); } + private void selectTab(int index) + { + var channel = channelTabControl.Items.Skip(index).FirstOrDefault(); + if (channel != null && channel.Name != "+") + channelTabControl.Current.Value = channel; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.AltPressed) + { + switch (e.Key) + { + case Key.Number1: + case Key.Number2: + case Key.Number3: + case Key.Number4: + case Key.Number5: + case Key.Number6: + case Key.Number7: + case Key.Number8: + case Key.Number9: + selectTab((int)e.Key - (int)Key.Number1); + return true; + case Key.Number0: + selectTab(9); + return true; + } + } + + return base.OnKeyDown(e); + } + public override bool AcceptsFocus => true; protected override void OnFocus(FocusEvent e) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index e31b349827..dddfddedef 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.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; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -18,7 +19,20 @@ namespace osu.Game.Overlays.Volume { public class MuteButton : Container, IHasCurrentValue { - public Bindable Current { get; } = new Bindable(); + private readonly Bindable current = new Bindable(); + + public Bindable Current + { + get => current; + set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + current.UnbindBindings(); + current.BindTo(value); + } + } private Color4 hoveredColour, unhoveredColour; private const float width = 100; diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 9509c7acae..c6f39b4705 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.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; using System.Collections.Generic; +using System.Linq; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,7 +13,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osuTK; using osu.Game.Graphics.Containers; -using System.Linq; using osu.Framework.Input.Events; namespace osu.Game.Screens.Play.HUD @@ -20,9 +21,20 @@ namespace osu.Game.Screens.Play.HUD { private const int fade_duration = 1000; - private readonly Bindable> mods = new Bindable>(); + private readonly Bindable> current = new Bindable>(); - public Bindable> Current => mods; + public Bindable> Current + { + get => current; + set + { + if (value == null) + throw new ArgumentNullException(nameof(value)); + + current.UnbindBindings(); + current.BindTo(value); + } + } private readonly FillFlowContainer iconsContainer; private readonly OsuSpriteText unrankedText; @@ -50,7 +62,7 @@ namespace osu.Game.Screens.Play.HUD } }; - mods.ValueChanged += mods => + Current.ValueChanged += mods => { iconsContainer.Clear(); foreach (Mod mod in mods) @@ -66,7 +78,7 @@ namespace osu.Game.Screens.Play.HUD protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - mods.UnbindAll(); + Current.UnbindAll(); } protected override void LoadComplete() @@ -77,7 +89,7 @@ namespace osu.Game.Screens.Play.HUD private void appearTransform() { - if (mods.Value.Any(m => !m.Ranked)) + if (Current.Value.Any(m => !m.Ranked)) unrankedText.FadeInFromZero(fade_duration, Easing.OutQuint); else unrankedText.Hide(); From e26958f90164e3979d97a72458061b4850731561 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Dec 2018 10:23:44 +0900 Subject: [PATCH 208/355] Fix targeting netcoreapp2.1 in many places --- .../runConfigurations/RulesetTests__catch_.xml | 2 +- .../runConfigurations/RulesetTests__mania_.xml | 2 +- .../runConfigurations/RulesetTests__osu__.xml | 2 +- .../runConfigurations/RulesetTests__taiko_.xml | 2 +- .../.idea/runConfigurations/VisualTests.xml | 2 +- .vscode/launch.json | 16 ++++++++-------- .vscode/tasks.json | 6 +----- .../.vscode/launch.json | 4 ++-- .../.vscode/launch.json | 4 ++-- osu.Game.Rulesets.Osu.Tests/.vscode/launch.json | 4 ++-- .../.vscode/launch.json | 4 ++-- 11 files changed, 22 insertions(+), 26 deletions(-) diff --git a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml b/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml index 1c988fe6fd..2eff16cc91 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/RulesetTests__catch_.xml @@ -1,6 +1,6 @@ - public class StandAloneChatDisplay : CompositeDrawable { + private readonly bool postingTextbox; + public readonly Bindable Channel = new Bindable(); - private readonly FillFlowContainer messagesFlow; - - private Channel lastChannel; - private readonly FocusedTextBox textbox; protected ChannelManager ChannelManager; + private ScrollContainer scroll; + + private DrawableChannel drawableChannel; + + private const float textbox_height = 30; + /// /// Construct a new instance. /// /// Whether a textbox for posting new messages should be displayed. public StandAloneChatDisplay(bool postingTextbox = false) { + this.postingTextbox = postingTextbox; CornerRadius = 10; Masking = true; @@ -50,23 +51,11 @@ namespace osu.Game.Online.Chat Alpha = 0.8f, RelativeSizeAxes = Axes.Both }, - messagesFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - LayoutEasing = Easing.Out, - LayoutDuration = 500, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Direction = FillDirection.Vertical - } }; - const float textbox_height = 30; if (postingTextbox) { - messagesFlow.Y -= textbox_height; AddInternal(textbox = new FocusedTextBox { RelativeSizeAxes = Axes.X, @@ -117,112 +106,43 @@ namespace osu.Game.Online.Chat this.MoveToY(100, 500, Easing.In); } - protected virtual Drawable CreateMessage(Message message) - { - return new StandAloneMessage(message); - } + protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message); private void channelChanged(Channel channel) { - if (lastChannel != null) - lastChannel.NewMessagesArrived -= newMessages; - - lastChannel = channel; - messagesFlow.Clear(); + drawableChannel?.Expire(); if (channel == null) return; - channel.NewMessagesArrived += newMessages; - - newMessages(channel.Messages); + AddInternal(drawableChannel = new StandAloneDrawableChannel(channel) + { + CreateChatLineAction = CreateMessage, + Padding = new MarginPadding { Bottom = postingTextbox ? textbox_height : 0 } + }); } - private void newMessages(IEnumerable messages) + protected class StandAloneDrawableChannel : DrawableChannel { - var excessChildren = messagesFlow.Children.Count - 10; - if (excessChildren > 0) - foreach (var c in messagesFlow.Children.Take(excessChildren)) - c.Expire(); + public Func CreateChatLineAction; - foreach (var message in messages) + protected override ChatLine CreateChatLine(Message m) => CreateChatLineAction(m); + + public StandAloneDrawableChannel(Channel channel) + : base(channel) { - var formatted = MessageFormatter.FormatMessage(message); - var drawable = CreateMessage(formatted); - drawable.Y = messagesFlow.Height; - messagesFlow.Add(drawable); + ChatLineFlow.Padding = new MarginPadding { Horizontal = 0 }; } } - protected class StandAloneMessage : CompositeDrawable + protected class StandAloneMessage : ChatLine { - protected readonly Message Message; - protected OsuSpriteText SenderText; - protected Circle ColourBox; + protected override float TextSize => 15; - public StandAloneMessage(Message message) + protected override float HorizontalPadding => 10; + protected override float MessagePadding => 120; + + public StandAloneMessage(Message message) : base(message) { - Message = message; - } - - [BackgroundDependencyLoader] - private void load() - { - Margin = new MarginPadding(3); - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - InternalChildren = new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - Width = 0.2f, - Children = new Drawable[] - { - SenderText = new OsuSpriteText - { - Font = @"Exo2.0-Bold", - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Text = Message.Sender.ToString() - } - } - }, - new Container - { - Size = new Vector2(8, OsuSpriteText.FONT_SIZE), - Margin = new MarginPadding { Horizontal = 3 }, - Children = new Drawable[] - { - ColourBox = new Circle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(8) - } - } - }, - new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.5f, - Text = Message.DisplayContent - } - } - } - }; - - if (!string.IsNullOrEmpty(Message.Sender.Colour)) - SenderText.Colour = ColourBox.Colour = OsuColour.FromHex(Message.Sender.Colour); } } } diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index c11de48430..29579056bf 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,72 +1,38 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// 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 osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Chat; using osu.Game.Users; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.Chat { - public class ChatLine : Container + public class ChatLine : CompositeDrawable { - private static readonly Color4[] username_colours = - { - OsuColour.FromHex("588c7e"), - OsuColour.FromHex("b2a367"), - OsuColour.FromHex("c98f65"), - OsuColour.FromHex("bc5151"), - OsuColour.FromHex("5c8bd6"), - OsuColour.FromHex("7f6ab7"), - OsuColour.FromHex("a368ad"), - OsuColour.FromHex("aa6880"), + public const float LEFT_PADDING = default_message_padding + default_horizontal_padding * 2; - OsuColour.FromHex("6fad9b"), - OsuColour.FromHex("f2e394"), - OsuColour.FromHex("f2ae72"), - OsuColour.FromHex("f98f8a"), - OsuColour.FromHex("7daef4"), - OsuColour.FromHex("a691f2"), - OsuColour.FromHex("c894d3"), - OsuColour.FromHex("d895b0"), + private const float default_message_padding = 200; - OsuColour.FromHex("53c4a1"), - OsuColour.FromHex("eace5c"), - OsuColour.FromHex("ea8c47"), - OsuColour.FromHex("fc4f4f"), - OsuColour.FromHex("3d94ea"), - OsuColour.FromHex("7760ea"), - OsuColour.FromHex("af52c6"), - OsuColour.FromHex("e25696"), + protected virtual float MessagePadding => default_message_padding; - OsuColour.FromHex("677c66"), - OsuColour.FromHex("9b8732"), - OsuColour.FromHex("8c5129"), - OsuColour.FromHex("8c3030"), - OsuColour.FromHex("1f5d91"), - OsuColour.FromHex("4335a5"), - OsuColour.FromHex("812a96"), - OsuColour.FromHex("992861"), - }; + private const float default_horizontal_padding = 15; - public const float LEFT_PADDING = message_padding + padding * 2; + protected virtual float HorizontalPadding => default_horizontal_padding; - private const float padding = 15; - private const float message_padding = 200; - private const float action_padding = 3; - private const float text_size = 20; + protected virtual float TextSize => 20; private Color4 customUsernameColour; @@ -75,14 +41,13 @@ namespace osu.Game.Overlays.Chat public ChatLine(Message message) { Message = message; - + Padding = new MarginPadding { Left = HorizontalPadding, Right = HorizontalPadding }; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - - Padding = new MarginPadding { Left = padding, Right = padding }; } - private ChannelManager chatManager; + [Resolved(CanBeNull = true)] + private ChannelManager chatManager { get; set; } private Message message; private OsuSpriteText username; @@ -106,10 +71,9 @@ namespace osu.Game.Overlays.Chat } } - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, ChannelManager chatManager) + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - this.chatManager = chatManager; customUsernameColour = colours.ChatBlue; } @@ -125,7 +89,7 @@ namespace osu.Game.Overlays.Chat { Font = @"Exo2.0-BoldItalic", Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], - TextSize = text_size, + TextSize = TextSize, }; if (hasBackground) @@ -163,11 +127,11 @@ namespace osu.Game.Overlays.Chat }; } - Children = new Drawable[] + InternalChildren = new Drawable[] { new Container { - Size = new Vector2(message_padding, text_size), + Size = new Vector2(MessagePadding, TextSize), Children = new Drawable[] { timestamp = new OsuSpriteText @@ -176,7 +140,7 @@ namespace osu.Game.Overlays.Chat Origin = Anchor.CentreLeft, Font = @"Exo2.0-SemiBold", FixedWidth = true, - TextSize = text_size * 0.75f, + TextSize = TextSize * 0.75f, }, new MessageSender(message.Sender) { @@ -191,7 +155,7 @@ namespace osu.Game.Overlays.Chat { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = message_padding + padding }, + Padding = new MarginPadding { Left = MessagePadding + HorizontalPadding }, Children = new Drawable[] { contentFlow = new LinkFlowContainer(t => @@ -204,7 +168,7 @@ namespace osu.Game.Overlays.Chat t.Colour = OsuColour.FromHex(message.Sender.Colour); } - t.TextSize = text_size; + t.TextSize = TextSize; }) { AutoSizeAxes = Axes.Y, @@ -257,5 +221,44 @@ namespace osu.Game.Overlays.Chat new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction), }; } + + private static readonly Color4[] username_colours = + { + OsuColour.FromHex("588c7e"), + OsuColour.FromHex("b2a367"), + OsuColour.FromHex("c98f65"), + OsuColour.FromHex("bc5151"), + OsuColour.FromHex("5c8bd6"), + OsuColour.FromHex("7f6ab7"), + OsuColour.FromHex("a368ad"), + OsuColour.FromHex("aa6880"), + + OsuColour.FromHex("6fad9b"), + OsuColour.FromHex("f2e394"), + OsuColour.FromHex("f2ae72"), + OsuColour.FromHex("f98f8a"), + OsuColour.FromHex("7daef4"), + OsuColour.FromHex("a691f2"), + OsuColour.FromHex("c894d3"), + OsuColour.FromHex("d895b0"), + + OsuColour.FromHex("53c4a1"), + OsuColour.FromHex("eace5c"), + OsuColour.FromHex("ea8c47"), + OsuColour.FromHex("fc4f4f"), + OsuColour.FromHex("3d94ea"), + OsuColour.FromHex("7760ea"), + OsuColour.FromHex("af52c6"), + OsuColour.FromHex("e25696"), + + OsuColour.FromHex("677c66"), + OsuColour.FromHex("9b8732"), + OsuColour.FromHex("8c5129"), + OsuColour.FromHex("8c3030"), + OsuColour.FromHex("1f5d91"), + OsuColour.FromHex("4335a5"), + OsuColour.FromHex("812a96"), + OsuColour.FromHex("992861"), + }; } } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 2418eda2b6..c8fc15a0bc 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Chat public class DrawableChannel : Container { public readonly Channel Channel; - private readonly ChatLineContainer flow; + protected readonly ChatLineContainer ChatLineFlow; private readonly ScrollContainer scroll; public DrawableChannel(Channel channel) @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Chat { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = flow = new ChatLineContainer + Child = ChatLineFlow = new ChatLineContainer { Padding = new MarginPadding { Left = 20, Right = 20 }, RelativeSizeAxes = Axes.X, @@ -72,17 +72,19 @@ namespace osu.Game.Overlays.Chat Channel.PendingMessageResolved -= pendingMessageResolved; } + protected virtual ChatLine CreateChatLine(Message m) => new ChatLine(m); + private void newMessagesArrived(IEnumerable newMessages) { // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MaxHistory)); - flow.AddRange(displayMessages.Select(m => new ChatLine(m))); + ChatLineFlow.AddRange(displayMessages.Select(CreateChatLine)); - if (scroll.IsScrolledToEnd(10) || !flow.Children.Any() || newMessages.Any(m => m is LocalMessage)) + if (scroll.IsScrolledToEnd(10) || !ChatLineFlow.Children.Any() || newMessages.Any(m => m is LocalMessage)) scrollToEnd(); - var staleMessages = flow.Children.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); + var staleMessages = ChatLineFlow.Children.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); int count = staleMessages.Length - Channel.MaxHistory; for (int i = 0; i < count; i++) @@ -96,25 +98,25 @@ namespace osu.Game.Overlays.Chat private void pendingMessageResolved(Message existing, Message updated) { - var found = flow.Children.LastOrDefault(c => c.Message == existing); + var found = ChatLineFlow.Children.LastOrDefault(c => c.Message == existing); if (found != null) { Trace.Assert(updated.Id.HasValue, "An updated message was returned with no ID."); - flow.Remove(found); + ChatLineFlow.Remove(found); found.Message = updated; - flow.Add(found); + ChatLineFlow.Add(found); } } private void messageRemoved(Message removed) { - flow.Children.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); + ChatLineFlow.Children.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); } private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd()); - private class ChatLineContainer : FillFlowContainer + protected class ChatLineContainer : FillFlowContainer { protected override int Compare(Drawable x, Drawable y) { From 4149734f89588a81494c9911f23e828aa2797cc7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 21 Dec 2018 18:22:13 +0900 Subject: [PATCH 218/355] Add room leaderboard to results --- osu.Game.Tests/Visual/TestCaseMultiResults.cs | 47 +++++++++ .../Match/Components/MatchLeaderboard.cs | 8 +- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- .../Screens/Multi/Play/TimeshiftPlayer.cs | 15 ++- .../Screens/Multi/Ranking/MultiResults.cs | 30 ++++++ .../Ranking/Pages/RoomRankingResultsPage.cs | 96 +++++++++++++++++++ .../Ranking/Types/RoomRankingResultType.cs | 31 ++++++ osu.Game/Screens/Play/Player.cs | 5 +- 8 files changed, 226 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMultiResults.cs create mode 100644 osu.Game/Screens/Multi/Ranking/MultiResults.cs create mode 100644 osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs create mode 100644 osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMultiResults.cs new file mode 100644 index 0000000000..53172b588c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMultiResults.cs @@ -0,0 +1,47 @@ +// 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 osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Scoring; +using osu.Game.Screens.Multi.Ranking; +using osu.Game.Screens.Multi.Ranking.Pages; +using osu.Game.Screens.Multi.Ranking.Types; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMultiResults : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(MultiResults), + typeof(RoomRankingResultType), + typeof(RoomRankingResultsPage) + }; + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0); + if (beatmapInfo != null) + Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); + + MultiResults res; + + Child = res = new MultiResults(new ScoreInfo + { + User = new User + { + Id = 9623649 + }, + }, new Room { RoomID = { Value = 46 } }); + } + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 9d4ad3cb22..4b09349be5 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -18,6 +18,8 @@ namespace osu.Game.Screens.Multi.Match.Components { public class MatchLeaderboard : Leaderboard { + public Action> ScoresLoaded; + private readonly Room room; public MatchLeaderboard(Room room) @@ -42,7 +44,11 @@ namespace osu.Game.Screens.Multi.Match.Components var req = new GetRoomScoresRequest(room.RoomID.Value ?? 0); - req.Success += r => scoresCallback?.Invoke(r); + req.Success += r => + { + scoresCallback?.Invoke(r); + ScoresLoaded?.Invoke(r); + }; return req; } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index b865c07e31..dfedf6d7a1 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -174,7 +174,7 @@ namespace osu.Game.Screens.Multi.Match { default: case GameTypeTimeshift _: - var player = new TimeshiftPlayer(room.RoomID.Value ?? 0, room.Playlist.First().ID); + var player = new TimeshiftPlayer(room, room.Playlist.First().ID); player.Exited += _ => leaderboard.RefreshScores(); pushGameplayScreen?.Invoke(new PlayerLoader(player)); diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 5d45615aa8..8e40544ccc 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -9,22 +9,25 @@ using osu.Framework.Allocation; using osu.Framework.IO.Network; using osu.Framework.Logging; using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; using osu.Game.Scoring; +using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Play; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Multi.Play { public class TimeshiftPlayer : Player { - private readonly int roomId; + private readonly Room room; private readonly int playlistItemId; [Resolved] private APIAccess api { get; set; } - public TimeshiftPlayer(int roomId, int playlistItemId) + public TimeshiftPlayer(Room room, int playlistItemId) { - this.roomId = roomId; + this.room = room; this.playlistItemId = playlistItemId; } @@ -37,7 +40,7 @@ namespace osu.Game.Screens.Multi.Play bool failed = false; - var req = new CreateScoreRequest(roomId, playlistItemId); + var req = new CreateScoreRequest(room.RoomID.Value ?? 0, playlistItemId); req.Success += r => token = r.ID; req.Failure += e => { @@ -64,12 +67,14 @@ namespace osu.Game.Screens.Multi.Play Debug.Assert(token != null); - var request = new SubmitScoreRequest(token.Value, roomId, playlistItemId, score); + var request = new SubmitScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score); request.Failure += e => Logger.Error(e, "Failed to submit score"); api.Queue(request); return score; } + + protected override Results CreateResults(ScoreInfo score) => new MultiResults(score, room); } public class SubmitScoreRequest : APIRequest diff --git a/osu.Game/Screens/Multi/Ranking/MultiResults.cs b/osu.Game/Screens/Multi/Ranking/MultiResults.cs new file mode 100644 index 0000000000..4358943057 --- /dev/null +++ b/osu.Game/Screens/Multi/Ranking/MultiResults.cs @@ -0,0 +1,30 @@ +// 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.Game.Online.Multiplayer; +using osu.Game.Scoring; +using osu.Game.Screens.Multi.Ranking.Types; +using osu.Game.Screens.Ranking; +using osu.Game.Screens.Ranking.Types; + +namespace osu.Game.Screens.Multi.Ranking +{ + public class MultiResults : Results + { + private readonly Room room; + + public MultiResults(ScoreInfo score, Room room) + : base(score) + { + this.room = room; + } + + protected override IEnumerable CreateResultTypes() => new IResultType[] + { + new ScoreResultType(Score, Beatmap), + new RankingResultType(Score, Beatmap), + new RoomRankingResultType(Score, Beatmap, room), + }; + } +} diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs new file mode 100644 index 0000000000..64c7d73322 --- /dev/null +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs @@ -0,0 +1,96 @@ +// 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 Microsoft.EntityFrameworkCore.Internal; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Lists; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Online.Leaderboards; +using osu.Game.Online.Multiplayer; +using osu.Game.Scoring; +using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Screens.Ranking.Pages; + +namespace osu.Game.Screens.Multi.Ranking.Pages +{ + public class RoomRankingResultsPage : ResultsPage + { + private readonly Room room; + + private OsuColour colours; + + private TextFlowContainer rankText; + + public RoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) + : base(score, beatmap) + { + this.room = room; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + this.colours = colours; + + Children = new Drawable[] + { + new Box + { + Colour = colours.GrayE, + RelativeSizeAxes = Axes.Both, + }, + new BufferedContainer + { + RelativeSizeAxes = Axes.Both, + BackgroundColour = colours.GrayE, + Children = new Drawable[] + { + new MatchLeaderboard(room) + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.8f, + Y = 95, + ScoresLoaded = scoresLoaded + } + } + }, + rankText = new TextFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Width = 0.5f, + AutoSizeAxes = Axes.Y, + Y = 75, + TextAnchor = Anchor.TopCentre + }, + }; + } + + private void scoresLoaded(IEnumerable scores) + { + Action gray = s => s.Colour = colours.Gray8; + + rankText.AddText("You are placed ", gray); + + int index = scores.IndexOf(new RoomScore { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); + + rankText.AddText($"#{index + 1} ", s => + { + s.Font = "Exo2.0-Bold"; + s.Colour = colours.YellowDark; + }); + + rankText.AddText("in the room!", gray); + } + } +} diff --git a/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs b/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs new file mode 100644 index 0000000000..378b650ea7 --- /dev/null +++ b/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.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.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Online.Multiplayer; +using osu.Game.Scoring; +using osu.Game.Screens.Multi.Ranking.Pages; +using osu.Game.Screens.Ranking.Pages; +using osu.Game.Screens.Ranking.Types; + +namespace osu.Game.Screens.Multi.Ranking.Types +{ + public class RoomRankingResultType : IResultType + { + private readonly ScoreInfo score; + private readonly WorkingBeatmap beatmap; + private readonly Room room; + + public RoomRankingResultType(ScoreInfo score, WorkingBeatmap beatmap, Room room) + { + this.score = score; + this.beatmap = beatmap; + this.room = room; + } + + public FontAwesome Icon => FontAwesome.fa_list; + + public ResultsPage CreatePage() => new RoomRankingResultsPage(score, beatmap, room); + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1429675ddd..f2390318b0 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -28,6 +28,7 @@ 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; @@ -287,7 +288,7 @@ namespace osu.Game.Screens.Play if (RulesetContainer.Replay == null) scoreManager.Import(score, true); - Push(new SoloResults(score)); + Push(CreateResults(score)); onCompletionEvent = null; }); @@ -431,5 +432,7 @@ namespace osu.Game.Screens.Play if (storyboardVisible && beatmap.Storyboard.ReplacesBackground) Background?.FadeTo(0, BACKGROUND_FADE_DURATION, Easing.OutQuint); } + + protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score); } } From 7e9cc4e8766160bb8a86099e9d702b867d6508aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 21 Dec 2018 18:37:33 +0900 Subject: [PATCH 219/355] Seed the results screen --- osu.Game.Tests/Visual/TestCaseMultiResults.cs | 93 +++++++++++++++++-- .../Ranking/Pages/RoomRankingResultsPage.cs | 25 +++-- .../Ranking/Types/RoomRankingResultType.cs | 2 +- 3 files changed, 98 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMultiResults.cs index 53172b588c..988ba0efdc 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiResults.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiResults.cs @@ -3,13 +3,18 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Game.Beatmaps; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Multi.Ranking.Pages; using osu.Game.Screens.Multi.Ranking.Types; +using osu.Game.Screens.Ranking.Pages; +using osu.Game.Screens.Ranking.Types; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -33,15 +38,87 @@ namespace osu.Game.Tests.Visual if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); - MultiResults res; - - Child = res = new MultiResults(new ScoreInfo + Child = new TestMultiResults(new ScoreInfo { - User = new User - { - Id = 9623649 - }, - }, new Room { RoomID = { Value = 46 } }); + User = new User { Id = 10 }, + }); + } + + private class TestMultiResults : MultiResults + { + private readonly Room room; + + public TestMultiResults(ScoreInfo score) + : this(score, new Room()) + { + } + + public TestMultiResults(ScoreInfo score, Room room) + : base(score, room) + { + this.room = room; + } + + protected override IEnumerable CreateResultTypes() => new IResultType[] + { + new ScoreResultType(Score, Beatmap), + new RankingResultType(Score, Beatmap), + new TestRoomRankingResultType(Score, Beatmap, room), + }; + } + + private class TestRoomRankingResultType : RoomRankingResultType + { + private readonly ScoreInfo score; + private readonly WorkingBeatmap beatmap; + private readonly Room room; + + public TestRoomRankingResultType(ScoreInfo score, WorkingBeatmap beatmap, Room room) + : base(score, beatmap, room) + { + this.score = score; + this.beatmap = beatmap; + this.room = room; + } + + public override ResultsPage CreatePage() => new TestRoomRankingResultsPage(score, beatmap, room); + } + + private class TestRoomRankingResultsPage : RoomRankingResultsPage + { + public TestRoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) + : base(score, beatmap, room) + { + } + + protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room); + } + + private class TestMatchLeaderboard : MatchLeaderboard + { + public TestMatchLeaderboard(Room room) + : base(room) + { + } + + protected override APIRequest FetchScores(Action> scoresCallback) + { + var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray(); + + scoresCallback?.Invoke(scores); + ScoresLoaded?.Invoke(scores); + + return null; + } + + private RoomScore createRoomScore(int id) => new RoomScore + { + User = new User { Id = id, Username = $"User {id}" }, + Accuracy = 0.98, + TotalScore = 987654, + TotalAttempts = 13, + CompletedAttempts = 5 + }; } } } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs index 64c7d73322..6c46973ca7 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Online.Leaderboards; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Match.Components; @@ -39,6 +38,8 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { this.colours = colours; + MatchLeaderboard leaderboard; + Children = new Drawable[] { new Box @@ -50,18 +51,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { RelativeSizeAxes = Axes.Both, BackgroundColour = colours.GrayE, - Children = new Drawable[] - { - new MatchLeaderboard(room) - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Height = 0.8f, - Y = 95, - ScoresLoaded = scoresLoaded - } - } + Child = leaderboard = CreateLeaderboard(room) }, rankText = new TextFlowContainer { @@ -74,6 +64,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages TextAnchor = Anchor.TopCentre }, }; + + leaderboard.Origin = Anchor.Centre; + leaderboard.Anchor = Anchor.Centre; + leaderboard.RelativeSizeAxes = Axes.Both; + leaderboard.Height = 0.8f; + leaderboard.Y = 95; + leaderboard.ScoresLoaded = scoresLoaded; } private void scoresLoaded(IEnumerable scores) @@ -92,5 +89,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages rankText.AddText("in the room!", gray); } + + protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new MatchLeaderboard(room); } } diff --git a/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs b/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs index 378b650ea7..963a9ff1cf 100644 --- a/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs +++ b/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs @@ -26,6 +26,6 @@ namespace osu.Game.Screens.Multi.Ranking.Types public FontAwesome Icon => FontAwesome.fa_list; - public ResultsPage CreatePage() => new RoomRankingResultsPage(score, beatmap, room); + public virtual ResultsPage CreatePage() => new RoomRankingResultsPage(score, beatmap, room); } } From 396caae0a90eace8b2b6da6bd91a516aadccc036 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Dec 2018 19:01:19 +0900 Subject: [PATCH 220/355] Remove redundant newline --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 46c6873063..1ec138ab57 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -53,7 +53,6 @@ namespace osu.Game.Online.Chat }, }; - if (postingTextbox) { AddInternal(textbox = new FocusedTextBox From 08d7c2df703bd60b364d43308f0bdb432f79b2e6 Mon Sep 17 00:00:00 2001 From: Poyo Date: Fri, 21 Dec 2018 16:08:08 -0800 Subject: [PATCH 221/355] Fix extra hard-rock flipping for sliders --- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 32d2d40671..1569e868b2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -26,9 +26,6 @@ namespace osu.Game.Rulesets.Osu.Mods if (slider == null) return; - slider.HeadCircle.Position = new Vector2(slider.HeadCircle.Position.X, OsuPlayfield.BASE_SIZE.Y - slider.HeadCircle.Position.Y); - slider.TailCircle.Position = new Vector2(slider.TailCircle.Position.X, OsuPlayfield.BASE_SIZE.Y - slider.TailCircle.Position.Y); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); From f0dfc75bb2024ed110871e2222089e940c1d9319 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 09:48:55 +0900 Subject: [PATCH 222/355] Change osu! default keys back to Z/X A/S was no better as far as keyboard layout agnostic-ness. And people are confused if we change the defaults. Need to take a step back and reassess. --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index ecb0443f33..5cfc24bdde 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -31,8 +31,8 @@ namespace osu.Game.Rulesets.Osu public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { - new KeyBinding(InputKey.A, OsuAction.LeftButton), - new KeyBinding(InputKey.S, OsuAction.RightButton), + new KeyBinding(InputKey.Z, OsuAction.LeftButton), + new KeyBinding(InputKey.X, OsuAction.RightButton), new KeyBinding(InputKey.MouseLeft, OsuAction.LeftButton), new KeyBinding(InputKey.MouseRight, OsuAction.RightButton), }; From dd0c04ea366ff94b72a6d562c759960bb733d631 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 12:45:36 +0900 Subject: [PATCH 223/355] Move RoomManager to multiplayer screen --- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 27 ++++++++++++++----- osu.Game/Screens/Multi/Multiplayer.cs | 6 ++++- osu.Game/Screens/Multi/RoomManager.cs | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 562dfaa347..a6d4d845e0 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -22,8 +22,8 @@ namespace osu.Game.Screens.Multi.Lounge private readonly RoomsContainer rooms; private readonly Action pushGameplayScreen; - [Cached] - private readonly RoomManager manager; + [Resolved] + private RoomManager roomManager { get; set; } public override string Title => "Lounge"; @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = rooms = new RoomsContainer { JoinRequested = r => manager?.JoinRoom(r) } + Child = rooms = new RoomsContainer { JoinRequested = r => roomManager?.JoinRoom(r) } }, }, inspector = new RoomInspector @@ -68,7 +68,6 @@ namespace osu.Game.Screens.Multi.Lounge }, }, }, - manager = new RoomManager { OpenRequested = Open } }; inspector.Room.BindTo(rooms.SelectedRoom); @@ -78,6 +77,12 @@ namespace osu.Game.Screens.Multi.Lounge Filter.Search.Exit += Exit; } + [BackgroundDependencyLoader] + private void load() + { + roomManager.OpenRequested += Open; + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -103,7 +108,7 @@ namespace osu.Game.Screens.Multi.Lounge protected override bool OnExiting(Screen next) { - manager?.PartRoom(); + roomManager?.PartRoom(); Filter.Search.HoldFocus = false; return base.OnExiting(next); @@ -111,7 +116,7 @@ namespace osu.Game.Screens.Multi.Lounge protected override void OnResuming(Screen last) { - manager?.PartRoom(); + roomManager?.PartRoom(); base.OnResuming(last); } @@ -125,7 +130,7 @@ namespace osu.Game.Screens.Multi.Lounge private void filterRooms() { rooms.Filter(Filter.CreateCriteria()); - manager.Filter(Filter.CreateCriteria()); + roomManager.Filter(Filter.CreateCriteria()); } public void Open(Room room) @@ -136,5 +141,13 @@ namespace osu.Game.Screens.Multi.Lounge Push(new MatchScreen(room, s => pushGameplayScreen?.Invoke(s))); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (roomManager != null) + roomManager.OpenRequested -= Open; + } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 9339c6693f..116d4137d5 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -31,6 +31,9 @@ namespace osu.Game.Screens.Multi private OsuScreen currentScreen; + [Cached] + private RoomManager roomManager; + public Multiplayer() { Child = waves = new MultiplayerWaveContainer @@ -80,7 +83,8 @@ namespace osu.Game.Screens.Multi }, Text = "Create room", Action = () => loungeScreen.Open(new Room()) - } + }, + roomManager = new RoomManager() }); screenAdded(loungeScreen); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index b3bb9cb147..dbc0fd3491 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Multi { public class RoomManager : PollingComponent { - public Action OpenRequested; + public event Action OpenRequested; public IBindableCollection Rooms => rooms; private readonly BindableCollection rooms = new BindableCollection(); From 1cb69c3478b91cc9a31c197bafc79102b3d5768e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 12:50:37 +0900 Subject: [PATCH 224/355] Split requests/responses into separate files --- .../Online/API/Requests/CreateRoomRequest.cs | 34 ++++++ .../API/Requests/CreateRoomScoreRequest.cs | 30 +++++ .../Online/API/Requests/GetRoomsRequest.cs | 44 +++++++ .../Online/API/Requests/JoinRoomRequest.cs | 31 +++++ .../Online/API/Requests/PartRoomRequest.cs | 31 +++++ .../API/Requests/Responses/APIRoomScore.cs | 13 +++ .../API/Requests/SubmitRoomScoreRequest.cs | 40 +++++++ .../Screens/Multi/Play/TimeshiftPlayer.cs | 65 +---------- osu.Game/Screens/Multi/RoomManager.cs | 107 +----------------- 9 files changed, 227 insertions(+), 168 deletions(-) create mode 100644 osu.Game/Online/API/Requests/CreateRoomRequest.cs create mode 100644 osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs create mode 100644 osu.Game/Online/API/Requests/GetRoomsRequest.cs create mode 100644 osu.Game/Online/API/Requests/JoinRoomRequest.cs create mode 100644 osu.Game/Online/API/Requests/PartRoomRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIRoomScore.cs create mode 100644 osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs diff --git a/osu.Game/Online/API/Requests/CreateRoomRequest.cs b/osu.Game/Online/API/Requests/CreateRoomRequest.cs new file mode 100644 index 0000000000..7ce289b65a --- /dev/null +++ b/osu.Game/Online/API/Requests/CreateRoomRequest.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.Net.Http; +using Newtonsoft.Json; +using osu.Framework.IO.Network; +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Online.API.Requests +{ + public class CreateRoomRequest : APIRequest + { + private readonly Room room; + + public CreateRoomRequest(Room room) + { + this.room = room; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.ContentType = "application/json"; + req.Method = HttpMethod.Post; + + req.AddRaw(JsonConvert.SerializeObject(room)); + + return req; + } + + protected override string Target => "rooms"; + } +} diff --git a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs b/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs new file mode 100644 index 0000000000..99640f435e --- /dev/null +++ b/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs @@ -0,0 +1,30 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Net.Http; +using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class CreateRoomScoreRequest : APIRequest + { + private readonly int roomId; + private readonly int playlistItemId; + + public CreateRoomScoreRequest(int roomId, int playlistItemId) + { + this.roomId = roomId; + this.playlistItemId = playlistItemId; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Post; + return req; + } + + protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores"; + } +} diff --git a/osu.Game/Online/API/Requests/GetRoomsRequest.cs b/osu.Game/Online/API/Requests/GetRoomsRequest.cs new file mode 100644 index 0000000000..bc835b1ab4 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetRoomsRequest.cs @@ -0,0 +1,44 @@ +// 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.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Lounge.Components; + +namespace osu.Game.Online.API.Requests +{ + public class GetRoomsRequest : APIRequest> + { + private readonly PrimaryFilter primaryFilter; + + public GetRoomsRequest(PrimaryFilter primaryFilter) + { + this.primaryFilter = primaryFilter; + } + + protected override string Target + { + get + { + string target = "rooms"; + + switch (primaryFilter) + { + case PrimaryFilter.Open: + break; + case PrimaryFilter.Owned: + target += "/owned"; + break; + case PrimaryFilter.Participated: + target += "/participated"; + break; + case PrimaryFilter.RecentlyEnded: + target += "/ended"; + break; + } + + return target; + } + } + } +} diff --git a/osu.Game/Online/API/Requests/JoinRoomRequest.cs b/osu.Game/Online/API/Requests/JoinRoomRequest.cs new file mode 100644 index 0000000000..b5e162da08 --- /dev/null +++ b/osu.Game/Online/API/Requests/JoinRoomRequest.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 System.Net.Http; +using osu.Framework.IO.Network; +using osu.Game.Online.Multiplayer; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests +{ + public class JoinRoomRequest : APIRequest + { + private readonly Room room; + private readonly User user; + + public JoinRoomRequest(Room room, User user) + { + this.room = room; + this.user = user; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Put; + return req; + } + + protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; + } +} diff --git a/osu.Game/Online/API/Requests/PartRoomRequest.cs b/osu.Game/Online/API/Requests/PartRoomRequest.cs new file mode 100644 index 0000000000..5e4457f69f --- /dev/null +++ b/osu.Game/Online/API/Requests/PartRoomRequest.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 System.Net.Http; +using osu.Framework.IO.Network; +using osu.Game.Online.Multiplayer; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests +{ + public class PartRoomRequest : APIRequest + { + private readonly Room room; + private readonly User user; + + public PartRoomRequest(Room room, User user) + { + this.room = room; + this.user = user; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Delete; + return req; + } + + protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIRoomScore.cs b/osu.Game/Online/API/Requests/Responses/APIRoomScore.cs new file mode 100644 index 0000000000..9bf67836f6 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIRoomScore.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 Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIRoomScore + { + [JsonProperty("id")] + public int ID { get; set; } + } +} diff --git a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs b/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs new file mode 100644 index 0000000000..d25e35db58 --- /dev/null +++ b/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Net.Http; +using Newtonsoft.Json; +using osu.Framework.IO.Network; +using osu.Game.Scoring; + +namespace osu.Game.Online.API.Requests +{ + public class SubmitRoomScoreRequest : APIRequest + { + private readonly int scoreId; + private readonly int roomId; + private readonly int playlistItemId; + private readonly ScoreInfo scoreInfo; + + public SubmitRoomScoreRequest(int scoreId, int roomId, int playlistItemId, ScoreInfo scoreInfo) + { + this.scoreId = scoreId; + this.roomId = roomId; + this.playlistItemId = playlistItemId; + this.scoreInfo = scoreInfo; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.ContentType = "application/json"; + req.Method = HttpMethod.Put; + + req.AddRaw(JsonConvert.SerializeObject(scoreInfo)); + + return req; + } + + protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores/{scoreId}"; + } +} diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 8e40544ccc..f33159f69b 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -2,13 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Diagnostics; -using System.Net.Http; using System.Threading; -using Newtonsoft.Json; using osu.Framework.Allocation; -using osu.Framework.IO.Network; using osu.Framework.Logging; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking; @@ -40,7 +38,7 @@ namespace osu.Game.Screens.Multi.Play bool failed = false; - var req = new CreateScoreRequest(room.RoomID.Value ?? 0, playlistItemId); + var req = new CreateRoomScoreRequest(room.RoomID.Value ?? 0, playlistItemId); req.Success += r => token = r.ID; req.Failure += e => { @@ -67,7 +65,7 @@ namespace osu.Game.Screens.Multi.Play Debug.Assert(token != null); - var request = new SubmitScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score); + var request = new SubmitRoomScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score); request.Failure += e => Logger.Error(e, "Failed to submit score"); api.Queue(request); @@ -76,61 +74,4 @@ namespace osu.Game.Screens.Multi.Play protected override Results CreateResults(ScoreInfo score) => new MultiResults(score, room); } - - public class SubmitScoreRequest : APIRequest - { - private readonly int scoreId; - private readonly int roomId; - private readonly int playlistItemId; - private readonly ScoreInfo scoreInfo; - - public SubmitScoreRequest(int scoreId, int roomId, int playlistItemId, ScoreInfo scoreInfo) - { - this.scoreId = scoreId; - this.roomId = roomId; - this.playlistItemId = playlistItemId; - this.scoreInfo = scoreInfo; - } - - protected override WebRequest CreateWebRequest() - { - var req = base.CreateWebRequest(); - - req.ContentType = "application/json"; - req.Method = HttpMethod.Put; - - req.AddRaw(JsonConvert.SerializeObject(scoreInfo)); - - return req; - } - - protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores/{scoreId}"; - } - - public class CreateScoreRequest : APIRequest - { - private readonly int roomId; - private readonly int playlistItemId; - - public CreateScoreRequest(int roomId, int playlistItemId) - { - this.roomId = roomId; - this.playlistItemId = playlistItemId; - } - - protected override WebRequest CreateWebRequest() - { - var req = base.CreateWebRequest(); - req.Method = HttpMethod.Post; - return req; - } - - protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores"; - } - - public class CreateScoreResult - { - [JsonProperty("id")] - public int ID { get; set; } - } } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index dbc0fd3491..17c3229b1a 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -2,22 +2,18 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using System.Linq; -using System.Net.Http; using System.Threading.Tasks; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.IO.Network; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Lounge.Components; -using osu.Game.Users; namespace osu.Game.Screens.Multi { @@ -148,106 +144,5 @@ namespace osu.Game.Screens.Multi foreach (var pi in room.Playlist) pi.MapObjects(beatmaps, rulesets); } - - private class CreateRoomRequest : APIRequest - { - private readonly Room room; - - public CreateRoomRequest(Room room) - { - this.room = room; - } - - protected override WebRequest CreateWebRequest() - { - var req = base.CreateWebRequest(); - - req.ContentType = "application/json"; - req.Method = HttpMethod.Post; - - req.AddRaw(JsonConvert.SerializeObject(room)); - - return req; - } - - protected override string Target => "rooms"; - } - - private class JoinRoomRequest : APIRequest - { - private readonly Room room; - private readonly User user; - - public JoinRoomRequest(Room room, User user) - { - this.room = room; - this.user = user; - } - - protected override WebRequest CreateWebRequest() - { - var req = base.CreateWebRequest(); - req.Method = HttpMethod.Put; - return req; - } - - protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; - } - - private class PartRoomRequest : APIRequest - { - private readonly Room room; - private readonly User user; - - public PartRoomRequest(Room room, User user) - { - this.room = room; - this.user = user; - } - - protected override WebRequest CreateWebRequest() - { - var req = base.CreateWebRequest(); - req.Method = HttpMethod.Delete; - return req; - } - - protected override string Target => $"rooms/{room.RoomID.Value}/users/{user.Id}"; - } - - private class GetRoomsRequest : APIRequest> - { - private readonly PrimaryFilter primaryFilter; - - public GetRoomsRequest(PrimaryFilter primaryFilter) - { - this.primaryFilter = primaryFilter; - } - - protected override string Target - { - get - { - string target = "rooms"; - - switch (primaryFilter) - { - case PrimaryFilter.Open: - break; - case PrimaryFilter.Owned: - target += "/owned"; - break; - case PrimaryFilter.Participated: - target += "/participated"; - break; - case PrimaryFilter.RecentlyEnded: - target += "/ended"; - break; - } - - return target; - } - } - } } } From f1a9a352fceba6a1a98c3e943daf529bff8048f8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:01:06 +0900 Subject: [PATCH 225/355] Cleanup bindable handling --- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 64 ++++++----- .../Visual/TestCaseMatchParticipants.cs | 24 +++-- .../Screens/Multi/Components/BeatmapTitle.cs | 30 +++--- .../Multi/Components/ParticipantCount.cs | 4 +- .../Multi/Lounge/Components/DrawableRoom.cs | 60 +++-------- .../Lounge/Components/ParticipantInfo.cs | 4 +- .../Multi/Lounge/Components/RoomInspector.cs | 73 +++---------- .../Screens/Multi/Match/Components/Header.cs | 8 +- .../Screens/Multi/Match/Components/Info.cs | 10 +- .../Multi/Match/Components/Participants.cs | 10 +- .../Match/Components/RoomSettingsOverlay.cs | 50 +++------ osu.Game/Screens/Multi/Match/MatchScreen.cs | 100 ++++++++--------- osu.Game/Screens/Multi/RoomBindings.cs | 101 ++++++++++++++++++ 13 files changed, 269 insertions(+), 269 deletions(-) create mode 100644 osu.Game/Screens/Multi/RoomBindings.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index 0d3c769dc5..be3367bf6c 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -26,38 +26,54 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - Info info = new Info(new Room()); + var room = new Room(); + + Info info = new Info(room); Add(info); - AddStep(@"set name", () => info.Name.Value = @"Room Name?"); - AddStep(@"set availability", () => info.Availability.Value = RoomAvailability.FriendsOnly); - AddStep(@"set status", () => info.Status.Value = new RoomStatusPlaying()); - AddStep(@"set beatmap", () => info.Beatmap.Value = new BeatmapInfo + AddStep(@"set name", () => room.Name.Value = @"Room Name?"); + AddStep(@"set availability", () => room.Availability.Value = RoomAvailability.FriendsOnly); + AddStep(@"set status", () => room.Status.Value = new RoomStatusPlaying()); + AddStep(@"set beatmap", () => { - StarDifficulty = 2.4, - Ruleset = rulesets.GetRuleset(0), - Metadata = new BeatmapMetadata + room.Playlist.Clear(); + room.Playlist.Add(new PlaylistItem { - Title = @"My Song", - Artist = @"VisualTests", - AuthorString = @"osu!lazer", - }, + Beatmap = new BeatmapInfo + { + StarDifficulty = 2.4, + Ruleset = rulesets.GetRuleset(0), + Metadata = new BeatmapMetadata + { + Title = @"My Song", + Artist = @"VisualTests", + AuthorString = @"osu!lazer", + }, + } + }); }); - AddStep(@"change name", () => info.Name.Value = @"Room Name!"); - AddStep(@"change availability", () => info.Availability.Value = RoomAvailability.InviteOnly); - AddStep(@"change status", () => info.Status.Value = new RoomStatusOpen()); - AddStep(@"null beatmap", () => info.Beatmap.Value = null); - AddStep(@"change beatmap", () => info.Beatmap.Value = new BeatmapInfo + AddStep(@"change name", () => room.Name.Value = @"Room Name!"); + AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.InviteOnly); + AddStep(@"change status", () => room.Status.Value = new RoomStatusOpen()); + AddStep(@"null beatmap", () => room.Playlist.Clear()); + AddStep(@"change beatmap", () => { - StarDifficulty = 4.2, - Ruleset = rulesets.GetRuleset(3), - Metadata = new BeatmapMetadata + room.Playlist.Clear(); + room.Playlist.Add(new PlaylistItem { - Title = @"Your Song", - Artist = @"Tester", - AuthorString = @"Someone", - }, + Beatmap = new BeatmapInfo + { + StarDifficulty = 4.2, + Ruleset = rulesets.GetRuleset(3), + Metadata = new BeatmapMetadata + { + Title = @"Your Song", + Artist = @"Tester", + AuthorString = @"Someone", + }, + } + }); }); } } diff --git a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs index 67a56e525f..27aeb9b5eb 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchParticipants.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 NUnit.Framework; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; @@ -11,16 +13,20 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseMatchParticipants : OsuTestCase { + private readonly Bindable maxParticipants = new Bindable(); + private readonly Bindable> users = new Bindable>(); + public TestCaseMatchParticipants() { Participants participants; - Add(participants = new Participants - { - RelativeSizeAxes = Axes.Both, - }); - AddStep(@"set max to null", () => participants.MaxParticipants.Value = null); - AddStep(@"set users", () => participants.Users.Value = new[] + Add(participants = new Participants { RelativeSizeAxes = Axes.Both }); + + participants.MaxParticipants.BindTo(maxParticipants); + participants.Users.BindTo(users); + + AddStep(@"set max to null", () => maxParticipants.Value = null); + AddStep(@"set users", () => users.Value = new[] { new User { @@ -48,9 +54,9 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set max", () => participants.MaxParticipants.Value = 10); - AddStep(@"clear users", () => participants.Users.Value = new User[] { }); - AddStep(@"set max to null", () => participants.MaxParticipants.Value = null); + AddStep(@"set max", () => maxParticipants.Value = 10); + AddStep(@"clear users", () => users.Value = new User[] { }); + AddStep(@"set max to null", () => maxParticipants.Value = null); } } } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index 67d414a080..d609f7a70d 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -14,21 +14,6 @@ namespace osu.Game.Screens.Multi.Components { public class BeatmapTitle : CompositeDrawable { - private float textSize = OsuSpriteText.FONT_SIZE; - - public float TextSize - { - get => textSize; - set - { - if (textSize == value) - return; - textSize = value; - - updateText(); - } - } - public readonly IBindable Beatmap = new Bindable(); private readonly LinkFlowContainer textFlow; @@ -48,6 +33,21 @@ namespace osu.Game.Screens.Multi.Components updateText(); } + private float textSize = OsuSpriteText.FONT_SIZE; + + public float TextSize + { + get => textSize; + set + { + if (textSize == value) + return; + textSize = value; + + updateText(); + } + } + private void updateText() { if (!IsLoaded) diff --git a/osu.Game/Screens/Multi/Components/ParticipantCount.cs b/osu.Game/Screens/Multi/Components/ParticipantCount.cs index 66f13ed683..8665678562 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantCount.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantCount.cs @@ -18,8 +18,8 @@ namespace osu.Game.Screens.Multi.Components private readonly OsuSpriteText slash, maxText; - public readonly Bindable> Participants = new Bindable>(); - public readonly Bindable MaxParticipants = new Bindable(); + public readonly IBindable> Participants = new Bindable>(); + public readonly IBindable MaxParticipants = new Bindable(); public ParticipantCount() { diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index f4e304d0a8..d6bc0018e4 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,7 +17,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; -using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -37,18 +34,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components public event Action StateChanged; + private readonly RoomBindings bindings = new RoomBindings(); + private readonly Box selectionBox; - - private readonly Bindable nameBind = new Bindable(); - private readonly Bindable hostBind = new Bindable(); - private readonly Bindable statusBind = new Bindable(); - private readonly Bindable typeBind = new Bindable(); - private readonly Bindable> participantsBind = new Bindable>(); - private readonly IBindableCollection playlistBind = new BindableCollection(); - private readonly IBindable endDateBind = new Bindable(); - - private readonly Bindable beatmap = new Bindable(); - private UpdateableBeatmapBackgroundSprite background; private BeatmapTitle beatmapTitle; private ModeTypeInfo modeTypeInfo; @@ -92,6 +80,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components public DrawableRoom(Room room) { Room = room; + bindings.Room = room; RelativeSizeAxes = Axes.X; Height = height + SELECTION_BORDER_WIDTH * 2; @@ -222,7 +211,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, }; - statusBind.ValueChanged += s => + bindings.Status.ValueChanged += s => { status.Text = s.Message; @@ -230,31 +219,15 @@ namespace osu.Game.Screens.Multi.Lounge.Components d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }; - nameBind.BindValueChanged(n => name.Text = n); + background.Beatmap.BindTo(bindings.CurrentBeatmap); + modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); + beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap); + modeTypeInfo.Type.BindTo(bindings.Type); + participantInfo.Host.BindTo(bindings.Host); + participantInfo.Participants.BindTo(bindings.Participants); - nameBind.BindTo(Room.Name); - hostBind.BindTo(Room.Host); - statusBind.BindTo(Room.Status); - typeBind.BindTo(Room.Type); - playlistBind.BindTo(Room.Playlist); - participantsBind.BindTo(Room.Participants); - endDateBind.BindTo(Room.EndDate); - - endDateBind.BindValueChanged(d => endDate.Date = d, true); - - background.Beatmap.BindTo(beatmap); - modeTypeInfo.Beatmap.BindTo(beatmap); - beatmapTitle.Beatmap.BindTo(beatmap); - - modeTypeInfo.Type.BindTo(typeBind); - - participantInfo.Host.BindTo(hostBind); - participantInfo.Participants.BindTo(participantsBind); - - playlistBind.ItemsAdded += _ => updatePlaylist(); - playlistBind.ItemsRemoved += _ => updatePlaylist(); - - updatePlaylist(); + bindings.Name.BindValueChanged(n => name.Text = n, true); + bindings.EndDate.BindValueChanged(d => endDate.Date = d, true); } protected override void LoadComplete() @@ -262,14 +235,5 @@ namespace osu.Game.Screens.Multi.Lounge.Components base.LoadComplete(); this.FadeInFromZero(transition_duration); } - - private void updatePlaylist() - { - if (playlistBind.Count == 0) - return; - - // For now, only the first playlist item is supported - beatmap.Value = playlistBind.First().Beatmap; - } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 042dd96b61..b0ce800d4b 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -21,8 +21,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components { private readonly FillFlowContainer levelRangeContainer; - public readonly Bindable Host = new Bindable(); - public readonly Bindable> Participants = new Bindable>(); + public readonly IBindable Host = new Bindable(); + public readonly IBindable> Participants = new Bindable>(); public ParticipantInfo(string rankPrefix = null) { diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index f290830334..08beace4ca 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.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.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -31,15 +30,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components public readonly IBindable Room = new Bindable(); private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; - private readonly Bindable nameBind = new Bindable(); - private readonly Bindable hostBind = new Bindable(); - private readonly Bindable statusBind = new Bindable(); - private readonly Bindable typeBind = new Bindable(); - private readonly Bindable maxParticipantsBind = new Bindable(); - private readonly Bindable> participantsBind = new Bindable>(); - private readonly IBindableCollection playlistBind = new BindableCollection(); - private readonly Bindable beatmap = new Bindable(); + private readonly RoomBindings bindings = new RoomBindings(); private OsuColour colours; private Box statusStrip; @@ -174,53 +166,27 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, }; - playlistBind.ItemsAdded += _ => updatePlaylist(); - playlistBind.ItemsRemoved += _ => updatePlaylist(); + participantInfo.Host.BindTo(bindings.Host); + participantInfo.Participants.BindTo(bindings.Participants); + participantCount.Participants.BindTo(bindings.Participants); + participantCount.MaxParticipants.BindTo(bindings.MaxParticipants); + beatmapTypeInfo.Type.BindTo(bindings.Type); + background.Beatmap.BindTo(bindings.CurrentBeatmap); + beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); - statusBind.BindValueChanged(displayStatus); - participantsBind.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); - - nameBind.BindValueChanged(n => name.Text = n); - - participantInfo.Host.BindTo(hostBind); - participantInfo.Participants.BindTo(participantsBind); - - participantCount.Participants.BindTo(participantsBind); - participantCount.MaxParticipants.BindTo(maxParticipantsBind); - - beatmapTypeInfo.Type.BindTo(typeBind); - - background.Beatmap.BindTo(beatmap); - beatmapTypeInfo.Beatmap.BindTo(beatmap); + bindings.Status.BindValueChanged(displayStatus); + bindings.Participants.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); + bindings.Name.BindValueChanged(n => name.Text = n); Room.BindValueChanged(updateRoom, true); } - private Room lastRoom; - - private void updateRoom(Room newRoom) + private void updateRoom(Room room) { - if (lastRoom != null) - { - nameBind.UnbindFrom(lastRoom.Name); - hostBind.UnbindFrom(lastRoom.Host); - statusBind.UnbindFrom(lastRoom.Status); - typeBind.UnbindFrom(lastRoom.Type); - playlistBind.UnbindFrom(lastRoom.Playlist); - maxParticipantsBind.UnbindFrom(lastRoom.MaxParticipants); - participantsBind.UnbindFrom(lastRoom.Participants); - } + bindings.Room = room; - if (newRoom != null) + if (room != null) { - nameBind.BindTo(newRoom.Name); - hostBind.BindTo(newRoom.Host); - statusBind.BindTo(newRoom.Status); - typeBind.BindTo(newRoom.Type); - playlistBind.BindTo(newRoom.Playlist); - maxParticipantsBind.BindTo(newRoom.MaxParticipants); - participantsBind.BindTo(newRoom.Participants); - participantsFlow.FadeIn(transition_duration); participantCount.FadeIn(transition_duration); beatmapTypeInfo.FadeIn(transition_duration); @@ -237,17 +203,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components displayStatus(new RoomStatusNoneSelected()); } - - lastRoom = newRoom; - } - - private void updatePlaylist() - { - if (playlistBind.Count == 0) - return; - - // For now, only the first playlist item is supported - beatmap.Value = playlistBind.First().Beatmap; } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 3f4f137413..f306ee698f 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -27,9 +27,9 @@ namespace osu.Game.Screens.Multi.Match.Components { public const float HEIGHT = 200; - public readonly Bindable Beatmap = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); public readonly IBindable Type = new Bindable(); - public readonly Bindable> Mods = new Bindable>(); + public readonly IBindable> Mods = new Bindable>(); private readonly Box tabStrip; @@ -116,11 +116,11 @@ namespace osu.Game.Screens.Multi.Match.Components beatmapTypeInfo.Beatmap.BindTo(Beatmap); beatmapTypeInfo.Type.BindTo(Type); - modDisplay.Current.BindTo(Mods); + background.Beatmap.BindTo(Beatmap); + Mods.BindValueChanged(m => modDisplay.Current.Value = m, true); beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); - background.Beatmap.BindTo(Beatmap); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index de02899a01..b849cae5d0 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -26,11 +26,11 @@ namespace osu.Game.Screens.Multi.Match.Components private OsuColour colours; - public readonly Bindable Name = new Bindable(); - public readonly Bindable Availability = new Bindable(); - public readonly Bindable Status = new Bindable(); - public readonly Bindable Beatmap = new Bindable(); - public readonly Bindable EndDate = new Bindable(); + public readonly IBindable Name = new Bindable(); + public readonly IBindable Availability = new Bindable(); + public readonly IBindable Status = new Bindable(); + public readonly IBindable Beatmap = new Bindable(); + public readonly IBindable EndDate = new Bindable(); public Info(Room room) { diff --git a/osu.Game/Screens/Multi/Match/Components/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs index 92732dc045..4f18fc9f4c 100644 --- a/osu.Game/Screens/Multi/Match/Components/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -15,14 +15,8 @@ namespace osu.Game.Screens.Multi.Match.Components { public class Participants : CompositeDrawable { - public readonly Bindable> Users = new Bindable>(); - public readonly Bindable MaxParticipants = new Bindable(); - - public new MarginPadding Padding - { - get => base.Padding; - set => base.Padding = value; - } + public readonly IBindable> Users = new Bindable>(); + public readonly IBindable MaxParticipants = new Bindable(); public Participants() { diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index bab44d62b2..65e1f068a8 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -4,7 +4,6 @@ using System; using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -24,12 +23,7 @@ namespace osu.Game.Screens.Multi.Match.Components private const float transition_duration = 350; private const float field_padding = 45; - private readonly Bindable nameBind = new Bindable(); - private readonly Bindable availabilityBind = new Bindable(); - private readonly Bindable typeBind = new Bindable(); - private readonly Bindable maxParticipantsBind = new Bindable(); - private readonly IBindableCollection playlistBind = new BindableCollection(); - private readonly Bindable durationBind = new Bindable(); + private readonly RoomBindings bindings = new RoomBindings(); private readonly Container content; @@ -51,6 +45,8 @@ namespace osu.Game.Screens.Multi.Match.Components { this.room = room; + bindings.Room = room; + Masking = true; Child = content = new Container @@ -189,11 +185,11 @@ namespace osu.Game.Screens.Multi.Match.Components TypePicker.Current.ValueChanged += t => typeLabel.Text = t.Name; - nameBind.ValueChanged += n => NameField.Text = n; - availabilityBind.ValueChanged += a => AvailabilityPicker.Current.Value = a; - typeBind.ValueChanged += t => TypePicker.Current.Value = t; - maxParticipantsBind.ValueChanged += m => MaxParticipantsField.Text = m?.ToString(); - durationBind.ValueChanged += d => DurationField.Current.Value = d; + bindings.Name.BindValueChanged(n => NameField.Text = n, true); + bindings.Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true); + bindings.Type.BindValueChanged(t => TypePicker.Current.Value = t, true); + bindings.MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true); + bindings.Duration.BindValueChanged(d => DurationField.Current.Value = d, true); } [BackgroundDependencyLoader] @@ -201,13 +197,6 @@ namespace osu.Game.Screens.Multi.Match.Components { typeLabel.Colour = colours.Yellow; - nameBind.BindTo(room.Name); - playlistBind.BindTo(room.Playlist); - availabilityBind.BindTo(room.Availability); - typeBind.BindTo(room.Type); - maxParticipantsBind.BindTo(room.MaxParticipants); - durationBind.BindTo(room.Duration); - MaxParticipantsField.ReadOnly = true; PasswordField.ReadOnly = true; AvailabilityPicker.ReadOnly.Value = true; @@ -222,19 +211,10 @@ namespace osu.Game.Screens.Multi.Match.Components ApplyButton.Enabled.Value = hasValidSettings; } - private bool hasValidSettings => NameField.Text.Length > 0 && playlistBind.Count > 0; + private bool hasValidSettings => NameField.Text.Length > 0 && bindings.Playlist.Count > 0; protected override void PopIn() { - // reapply the rooms values if the overlay was completely closed - if (content.Y == -1) - { - nameBind.TriggerChange(); - availabilityBind.TriggerChange(); - typeBind.TriggerChange(); - maxParticipantsBind.TriggerChange(); - } - content.MoveToY(0, transition_duration, Easing.OutQuint); } @@ -245,16 +225,16 @@ namespace osu.Game.Screens.Multi.Match.Components private void apply() { - nameBind.Value = NameField.Text; - availabilityBind.Value = AvailabilityPicker.Current.Value; - typeBind.Value = TypePicker.Current.Value; + bindings.Name.Value = NameField.Text; + bindings.Availability.Value = AvailabilityPicker.Current.Value; + bindings.Type.Value = TypePicker.Current.Value; if (int.TryParse(MaxParticipantsField.Text, out int max)) - maxParticipantsBind.Value = max; + bindings.MaxParticipants.Value = max; else - maxParticipantsBind.Value = null; + bindings.MaxParticipants.Value = null; - durationBind.Value = DurationField.Current.Value; + bindings.Duration.Value = DurationField.Current.Value; manager?.CreateRoom(room); } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index dfedf6d7a1..98a980afb2 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -5,39 +5,28 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; using osu.Game.Screens.Play; using osu.Game.Screens.Select; -using osu.Game.Users; namespace osu.Game.Screens.Multi.Match { public class MatchScreen : MultiplayerScreen { - private readonly Bindable nameBind = new Bindable(); - private readonly Bindable statusBind = new Bindable(); - private readonly Bindable availabilityBind = new Bindable(); - private readonly Bindable typeBind = new Bindable(); - private readonly Bindable maxParticipantsBind = new Bindable(); - private readonly Bindable> participantsBind = new Bindable>(); - private readonly BindableCollection playlistBind = new BindableCollection(); - private readonly Bindable endDateBind = new Bindable(); - public override bool AllowBeatmapRulesetChange => false; - public override string Title => room.Name.Value; - public override string ShortTitle => "room"; - private readonly Components.Header header; - private readonly Info info; + private readonly RoomBindings bindings = new RoomBindings(); + private readonly MatchLeaderboard leaderboard; private readonly Action pushGameplayScreen; @@ -58,14 +47,10 @@ namespace osu.Game.Screens.Multi.Match this.room = room; this.pushGameplayScreen = pushGameplayScreen; - nameBind.BindTo(room.Name); - statusBind.BindTo(room.Status); - availabilityBind.BindTo(room.Availability); - typeBind.BindTo(room.Type); - participantsBind.BindTo(room.Participants); - maxParticipantsBind.BindTo(room.MaxParticipants); - endDateBind.BindTo(room.EndDate); + bindings.Room = room; + Info info; + Components.Header header; RoomSettingsOverlay settings; Children = new Drawable[] @@ -113,7 +98,6 @@ namespace osu.Game.Screens.Multi.Match }; header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect { Selected = addPlaylistItem }); - header.Tabs.Current.ValueChanged += t => { if (t is SettingsMatchPage) @@ -122,55 +106,55 @@ namespace osu.Game.Screens.Multi.Match settings.Hide(); }; - info.Name.BindTo(nameBind); - info.Status.BindTo(statusBind); - info.Availability.BindTo(availabilityBind); - info.EndDate.BindTo(endDateBind); - - header.Type.BindTo(typeBind); - - playlistBind.ItemsAdded += _ => setFromPlaylist(); - playlistBind.ItemsRemoved += _ => setFromPlaylist(); + info.Name.BindTo(bindings.Name); + info.Status.BindTo(bindings.Status); + info.Availability.BindTo(bindings.Availability); + info.EndDate.BindTo(bindings.EndDate); + info.Beatmap.BindTo(bindings.CurrentBeatmap); + header.Type.BindTo(bindings.Type); + header.Beatmap.BindTo(bindings.CurrentBeatmap); + header.Mods.BindTo(bindings.CurrentMods); } protected override void LoadComplete() { base.LoadComplete(); - playlistBind.BindTo(room.Playlist); + bindings.CurrentBeatmap.BindValueChanged(setBeatmap, true); + bindings.CurrentMods.BindValueChanged(setMods, true); + bindings.CurrentRuleset.BindValueChanged(setRuleset, true); + } + + private void setBeatmap(BeatmapInfo beatmap) + { + // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info + var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID); + + game.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); + } + + private void setMods(IEnumerable mods) + { + Beatmap.Value.Mods.Value = mods.ToArray(); + } + + private void setRuleset(RulesetInfo ruleset) + { + if (ruleset == null) + return; + + game.ForcefullySetRuleset(ruleset); } private void addPlaylistItem(PlaylistItem item) { - playlistBind.Clear(); - playlistBind.Add(item); - } - - private void setFromPlaylist() - { - if (playlistBind.Count == 0) - return; - - // For now, only the first playlist item is supported - var item = playlistBind.First(); - - header.Beatmap.Value = item.Beatmap; - header.Mods.Value = item.RequiredMods; - info.Beatmap.Value = item.Beatmap; - - // Todo: item.Beatmap can be null here... - var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.BeatmapID) ?? item.Beatmap; - - var newBeatmap = beatmapManager.GetWorkingBeatmap(localBeatmap); - newBeatmap.Mods.Value = item.RequiredMods.ToArray(); - - game.ForcefullySetBeatmap(newBeatmap); - game.ForcefullySetRuleset(item.Ruleset); + bindings.Playlist.Clear(); + bindings.Playlist.Add(item); } private void onStart() { - switch (typeBind.Value) + switch (bindings.Type.Value) { default: case GameTypeTimeshift _: diff --git a/osu.Game/Screens/Multi/RoomBindings.cs b/osu.Game/Screens/Multi/RoomBindings.cs new file mode 100644 index 0000000000..b5854bf957 --- /dev/null +++ b/osu.Game/Screens/Multi/RoomBindings.cs @@ -0,0 +1,101 @@ +// 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 osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Users; + +namespace osu.Game.Screens.Multi +{ + /// + /// Helper class which binds to values from a . + /// + public class RoomBindings + { + public RoomBindings() + { + Playlist.ItemsAdded += _ => updatePlaylist(); + Playlist.ItemsRemoved += _ => updatePlaylist(); + } + + private Room room; + + /// + /// The to bind to. + /// + public Room Room + { + get => room; + set + { + if (room == value) + return; + + if (room != null) + { + Name.UnbindFrom(room.Name); + Host.UnbindFrom(room.Host); + Status.UnbindFrom(room.Status); + Type.UnbindFrom(room.Type); + Playlist.UnbindFrom(room.Playlist); + MaxParticipants.UnbindFrom(room.MaxParticipants); + Participants.UnbindFrom(room.Participants); + Availability.UnbindFrom(room.Availability); + Duration.UnbindFrom(room.Duration); + } + + room = value; + + if (room != null) + { + Name.BindTo(room.Name); + Host.BindTo(room.Host); + Status.BindTo(room.Status); + Type.BindTo(room.Type); + Playlist.BindTo(room.Playlist); + MaxParticipants.BindTo(room.MaxParticipants); + Participants.BindTo(room.Participants); + Availability.BindTo(room.Availability); + Duration.BindTo(room.Duration); + } + } + } + + private void updatePlaylist() + { + // Todo: We only ever have one playlist item for now. In the future, this will be user-settable + + var playlistItem = Playlist.FirstOrDefault(); + + currentBeatmap.Value = playlistItem?.Beatmap; + currentMods.Value = playlistItem?.RequiredMods ?? Enumerable.Empty(); + currentRuleset.Value = playlistItem?.Ruleset; + } + + public readonly Bindable Name = new Bindable(); + public readonly Bindable Host = new Bindable(); + public readonly Bindable Status = new Bindable(); + public readonly Bindable Type = new Bindable(); + public readonly BindableCollection Playlist = new BindableCollection(); + public readonly Bindable> Participants = new Bindable>(); + public readonly Bindable MaxParticipants = new Bindable(); + public readonly Bindable EndDate = new Bindable(); + public readonly Bindable Availability = new Bindable(); + public readonly Bindable Duration = new Bindable(); + + private readonly Bindable currentBeatmap = new Bindable(); + public IBindable CurrentBeatmap => currentBeatmap; + + private readonly Bindable> currentMods = new Bindable>(); + public IBindable> CurrentMods => currentMods; + + private readonly Bindable currentRuleset = new Bindable(); + public IBindable CurrentRuleset = new Bindable(); + } +} From 86ce0b551937f65f5b687430bf792d872a644ba1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 12:44:51 +0900 Subject: [PATCH 226/355] Make DrawableDate adjustable --- osu.Game/Graphics/DrawableDate.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 28f8bdf82f..639a549936 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -4,6 +4,7 @@ using System; using Humanizer; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Sprites; @@ -11,13 +12,27 @@ namespace osu.Game.Graphics { public class DrawableDate : OsuSpriteText, IHasTooltip { - protected readonly DateTimeOffset Date; + private DateTimeOffset date; + + public DateTimeOffset Date + { + get => date; + set + { + if (date == value) + return; + date = value.ToLocalTime(); + + if (LoadState >= LoadState.Ready) + updateTime(); + } + } public DrawableDate(DateTimeOffset date) { Font = "Exo2.0-RegularItalic"; - Date = date.ToLocalTime(); + Date = date; } [BackgroundDependencyLoader] From d28c754256c7258d59f0c5cd0ad4289b8787ad58 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Dec 2018 13:07:43 +0900 Subject: [PATCH 227/355] Fix negative dates, and time moving in opposite direction --- osu.Game/Graphics/DrawableDate.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 639a549936..87711c72c7 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -54,14 +54,14 @@ namespace osu.Game.Graphics var diffToNow = DateTimeOffset.Now.Subtract(Date); double timeUntilNextUpdate = 1000; - if (diffToNow.TotalSeconds > 60) + if (Math.Abs(diffToNow.TotalSeconds) > 120) { timeUntilNextUpdate *= 60; - if (diffToNow.TotalMinutes > 60) + if (Math.Abs(diffToNow.TotalMinutes) > 120) { timeUntilNextUpdate *= 60; - if (diffToNow.TotalHours > 24) + if (Math.Abs(diffToNow.TotalHours) > 48) timeUntilNextUpdate *= 24; } } From c06cf5d379cf0ca409f5ebb45051de69a366c064 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:08:00 +0900 Subject: [PATCH 228/355] Decouple match info from match screen --- .../Screens/Multi/Match/Components/Info.cs | 28 ++++++++----------- osu.Game/Screens/Multi/Match/MatchScreen.cs | 8 +----- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index b849cae5d0..ca1ca5f40f 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -3,12 +3,10 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; @@ -26,11 +24,7 @@ namespace osu.Game.Screens.Multi.Match.Components private OsuColour colours; - public readonly IBindable Name = new Bindable(); - public readonly IBindable Availability = new Bindable(); - public readonly IBindable Status = new Bindable(); - public readonly IBindable Beatmap = new Bindable(); - public readonly IBindable EndDate = new Bindable(); + private readonly RoomBindings bindings = new RoomBindings(); public Info(Room room) { @@ -99,13 +93,15 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - viewBeatmapButton.Beatmap.BindTo(Beatmap); - readyButton.Beatmap.BindTo(Beatmap); + viewBeatmapButton.Beatmap.BindTo(bindings.CurrentBeatmap); + readyButton.Beatmap.BindTo(bindings.CurrentBeatmap); - Availability.BindValueChanged(_ => updateAvailabilityStatus()); - Status.BindValueChanged(_ => updateAvailabilityStatus()); - Name.BindValueChanged(n => name.Text = n); - EndDate.BindValueChanged(d => endDate.Date = d); + bindings.Availability.BindValueChanged(_ => updateAvailabilityStatus()); + bindings.Status.BindValueChanged(_ => updateAvailabilityStatus()); + bindings.Name.BindValueChanged(n => name.Text = n); + bindings.EndDate.BindValueChanged(d => endDate.Date = d); + + bindings.Room = room; } [BackgroundDependencyLoader] @@ -126,10 +122,10 @@ namespace osu.Game.Screens.Multi.Match.Components if (!IsLoaded) return; - if (Status.Value != null) + if (bindings.Status.Value != null) { - availabilityStatus.FadeColour(Status.Value.GetAppropriateColour(colours), 100); - availabilityStatus.Text = $"{Availability.Value.GetDescription()}, {Status.Value.Message}"; + availabilityStatus.FadeColour(bindings.Status.Value.GetAppropriateColour(colours), 100); + availabilityStatus.Text = $"{bindings.Availability.Value.GetDescription()}, {bindings.Status.Value.Message}"; } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 98a980afb2..513b49713a 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -49,7 +49,6 @@ namespace osu.Game.Screens.Multi.Match bindings.Room = room; - Info info; Components.Header header; RoomSettingsOverlay settings; @@ -61,7 +60,7 @@ namespace osu.Game.Screens.Multi.Match Content = new[] { new Drawable[] { header = new Components.Header(room) { Depth = -1 } }, - new Drawable[] { info = new Info(room) { OnStart = onStart } }, + new Drawable[] { new Info(room) { OnStart = onStart } }, new Drawable[] { new GridContainer @@ -106,11 +105,6 @@ namespace osu.Game.Screens.Multi.Match settings.Hide(); }; - info.Name.BindTo(bindings.Name); - info.Status.BindTo(bindings.Status); - info.Availability.BindTo(bindings.Availability); - info.EndDate.BindTo(bindings.EndDate); - info.Beatmap.BindTo(bindings.CurrentBeatmap); header.Type.BindTo(bindings.Type); header.Beatmap.BindTo(bindings.CurrentBeatmap); header.Mods.BindTo(bindings.CurrentMods); From 21cfe5a3e67b253b1e05175ecf6160c9381801cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:12:27 +0900 Subject: [PATCH 229/355] Decouple header from matchscreen --- osu.Game.Tests/Visual/TestCaseMatchHeader.cs | 45 +++++++++---------- .../Screens/Multi/Match/Components/Header.cs | 18 +++----- osu.Game/Screens/Multi/Match/MatchScreen.cs | 4 -- 3 files changed, 27 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs index 8ff16a20b9..ac964e22a6 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; -using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi.Match.Components; @@ -20,37 +18,34 @@ namespace osu.Game.Tests.Visual typeof(Header) }; - private readonly Bindable beatmap = new Bindable(); - private readonly Bindable type = new Bindable(); - private readonly Bindable> mods = new Bindable>(); - public TestCaseMatchHeader() { - var header = new Header(new Room()); + var room = new Room(); - header.Beatmap.BindTo(beatmap); - header.Type.BindTo(type); - header.Mods.BindTo(mods); + var header = new Header(room); - beatmap.Value = new BeatmapInfo + room.Playlist.Add(new PlaylistItem { - Metadata = new BeatmapMetadata + Beatmap = new BeatmapInfo { - Title = "Title", - Artist = "Artist", - AuthorString = "Author", + Metadata = new BeatmapMetadata + { + Title = "Title", + Artist = "Artist", + AuthorString = "Author", + }, + Version = "Version", + Ruleset = new OsuRuleset().RulesetInfo }, - Version = "Version", - Ruleset = new OsuRuleset().RulesetInfo - }; + RequiredMods = + { + new OsuModDoubleTime(), + new OsuModNoFail(), + new OsuModRelax(), + } + }); - type.Value = new GameTypeTimeshift(); - mods.Value = new Mod[] - { - new OsuModDoubleTime(), - new OsuModNoFail(), - new OsuModRelax(), - }; + room.Type.Value = new GameTypeTimeshift(); Child = header; } diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index f306ee698f..b2d39151c1 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.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.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -10,12 +9,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Play.HUD; using osuTK; @@ -27,9 +24,7 @@ namespace osu.Game.Screens.Multi.Match.Components { public const float HEIGHT = 200; - public readonly IBindable Beatmap = new Bindable(); - public readonly IBindable Type = new Bindable(); - public readonly IBindable> Mods = new Bindable>(); + private readonly RoomBindings bindings = new RoomBindings(); private readonly Box tabStrip; @@ -42,6 +37,8 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.X; Height = HEIGHT; + bindings.Room = room; + BeatmapTypeInfo beatmapTypeInfo; BeatmapSelectButton beatmapButton; UpdateableBeatmapBackgroundSprite background; @@ -114,13 +111,12 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - beatmapTypeInfo.Beatmap.BindTo(Beatmap); - beatmapTypeInfo.Type.BindTo(Type); - background.Beatmap.BindTo(Beatmap); - Mods.BindValueChanged(m => modDisplay.Current.Value = m, true); + beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); + beatmapTypeInfo.Type.BindTo(bindings.Type); + background.Beatmap.BindTo(bindings.CurrentBeatmap); + bindings.CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true); beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); - } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 513b49713a..9a5950417b 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -104,10 +104,6 @@ namespace osu.Game.Screens.Multi.Match else settings.Hide(); }; - - header.Type.BindTo(bindings.Type); - header.Beatmap.BindTo(bindings.CurrentBeatmap); - header.Mods.BindTo(bindings.CurrentMods); } protected override void LoadComplete() From 7191233be8ed55d5a5a7520951bf067559a8f38f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:14:14 +0900 Subject: [PATCH 230/355] Allow roommanager to be null --- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index a6d4d845e0..8be7afad8b 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Multi.Lounge private readonly RoomsContainer rooms; private readonly Action pushGameplayScreen; - [Resolved] + [Resolved(CanBeNull = true)] private RoomManager roomManager { get; set; } public override string Title => "Lounge"; @@ -80,7 +80,8 @@ namespace osu.Game.Screens.Multi.Lounge [BackgroundDependencyLoader] private void load() { - roomManager.OpenRequested += Open; + if (roomManager != null) + roomManager.OpenRequested += Open; } protected override void UpdateAfterChildren() @@ -130,7 +131,7 @@ namespace osu.Game.Screens.Multi.Lounge private void filterRooms() { rooms.Filter(Filter.CreateCriteria()); - roomManager.Filter(Filter.CreateCriteria()); + roomManager?.Filter(Filter.CreateCriteria()); } public void Open(Room room) From 621480af0214f2e4e86199a0f667b70d431c895b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 14:21:21 +0900 Subject: [PATCH 231/355] Add simple (non-automated) test --- osu.Game.Tests/Visual/TestCaseDrawableDate.cs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseDrawableDate.cs diff --git a/osu.Game.Tests/Visual/TestCaseDrawableDate.cs b/osu.Game.Tests/Visual/TestCaseDrawableDate.cs new file mode 100644 index 0000000000..2e38f5eb28 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseDrawableDate.cs @@ -0,0 +1,67 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseDrawableDate : OsuTestCase + { + public TestCaseDrawableDate() + { + Child = new FillFlowContainer + { + Direction = FillDirection.Vertical, + AutoSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Children = new Drawable[] + { + new PokeyDrawableDate(DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(60))), + new PokeyDrawableDate(DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(55))), + new PokeyDrawableDate(DateTimeOffset.Now.Subtract(TimeSpan.FromSeconds(50))), + new PokeyDrawableDate(DateTimeOffset.Now), + new PokeyDrawableDate(DateTimeOffset.Now.Add(TimeSpan.FromSeconds(60))), + new PokeyDrawableDate(DateTimeOffset.Now.Add(TimeSpan.FromSeconds(65))), + new PokeyDrawableDate(DateTimeOffset.Now.Add(TimeSpan.FromSeconds(70))), + } + }; + } + + private class PokeyDrawableDate : CompositeDrawable + { + public PokeyDrawableDate(DateTimeOffset date) + { + const float box_size = 10; + + DrawableDate drawableDate; + Box flash; + + AutoSizeAxes = Axes.Both; + InternalChildren = new Drawable[] + { + flash = new Box + { + Colour = Color4.Yellow, + Size = new Vector2(box_size), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Alpha = 0 + }, + drawableDate = new DrawableDate(date) + { + X = box_size + 2, + } + }; + + drawableDate.Current.ValueChanged += v => flash.FadeOutFromOne(500); + } + } + } +} From f47ac3552218182fdbd7c6e928e48469df717e54 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Dec 2018 20:08:22 +0900 Subject: [PATCH 232/355] Add click to avatar --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 12 +---- osu.Game/Overlays/Profile/ProfileHeader.cs | 1 + .../Overlays/Toolbar/ToolbarUserButton.cs | 1 + osu.Game/Users/Avatar.cs | 51 +++++++++++++++++-- osu.Game/Users/UpdateableAvatar.cs | 23 ++++++--- osu.Game/Users/UserPanel.cs | 1 + 6 files changed, 67 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index c2f03a4b66..0b260d4f39 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -9,7 +9,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using osu.Framework.Allocation; using osu.Game.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -20,7 +19,6 @@ namespace osu.Game.Overlays.BeatmapSet private const float height = 50; private readonly UpdateableAvatar avatar; - private readonly ClickableArea clickableArea; private readonly FillFlowContainer fields; private BeatmapSetInfo beatmapSet; @@ -73,7 +71,7 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { - clickableArea = new ClickableArea + new Container { AutoSizeAxes = Axes.Both, CornerRadius = 3, @@ -100,14 +98,8 @@ namespace osu.Game.Overlays.BeatmapSet }; } - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay profile) + private void load() { - clickableArea.Action = () => - { - if (avatar.User != null) profile?.ShowUser(avatar.User); - }; - updateDisplay(); } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index a8075ec295..3c7fe0b1eb 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -82,6 +82,7 @@ namespace osu.Game.Overlays.Profile Origin = Anchor.BottomLeft, Masking = true, CornerRadius = 5, + OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 017d748600..36299e51f0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Toolbar Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, CornerRadius = 4, + OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index e6e1ba3c53..24864cce51 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -3,17 +3,29 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; namespace osu.Game.Users { public class Avatar : Container { + /// + /// Whether to open the user's profile when clicked. + /// + public readonly BindableBool OpenOnClick = new BindableBool(true); + private readonly User user; + [Resolved(CanBeNull = true)] + private OsuGame game { get; set; } + /// /// An avatar for specified user. /// @@ -33,14 +45,43 @@ namespace osu.Game.Users if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); if (texture == null) texture = textures.Get(@"Online/avatar-guest"); - Add(new Sprite + ClickableArea clickableArea; + Add(clickableArea = new ClickableArea { RelativeSizeAxes = Axes.Both, - Texture = texture, - FillMode = FillMode.Fit, - Anchor = Anchor.Centre, - Origin = Anchor.Centre + Child = new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = texture, + FillMode = FillMode.Fit, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, + Action = openProfile }); + + clickableArea.Enabled.BindTo(OpenOnClick); + } + + private void openProfile() + { + if (!OpenOnClick) + return; + + if (user != null) + game?.ShowUser(user.Id); + } + + private class ClickableArea : OsuClickableContainer, IHasTooltip + { + public string TooltipText => Enabled.Value ? @"View Profile" : null; + + protected override bool OnClick(ClickEvent e) + { + if (!Enabled) + return false; + return base.OnClick(e); + } } } } diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index 6c0b841abf..a8d9d3d66b 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.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.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,6 +36,11 @@ namespace osu.Game.Users } } + /// + /// Whether to open the user's profile when clicked. + /// + public readonly BindableBool OpenOnClick = new BindableBool(true); + protected override void LoadComplete() { base.LoadComplete(); @@ -45,15 +51,18 @@ namespace osu.Game.Users { displayedAvatar?.FadeOut(300); displayedAvatar?.Expire(); + if (user != null || ShowGuestOnNull) { - Add(displayedAvatar = new DelayedLoadWrapper( - new Avatar(user) - { - RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), - }) - ); + var avatar = new Avatar(user) + { + RelativeSizeAxes = Axes.Both, + OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), + }; + + avatar.OpenOnClick.BindTo(OpenOnClick); + + Add(displayedAvatar = new DelayedLoadWrapper(avatar)); } } } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d86f608bd1..1d302ef04f 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -99,6 +99,7 @@ namespace osu.Game.Users User = user, Masking = true, CornerRadius = 5, + OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, From dbd391825aced3fb7ac510dcb1bcbdc50a778232 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:29:27 +0900 Subject: [PATCH 233/355] Rework+fix TestCaseMultiHeader --- osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 30 +++++++++++++++----- osu.Game/Screens/Multi/Header.cs | 3 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index deb098e97d..2005c707b1 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -3,8 +3,8 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Game.Screens; using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Lounge; namespace osu.Game.Tests.Visual { @@ -13,15 +13,31 @@ namespace osu.Game.Tests.Visual { public TestCaseMultiHeader() { - LoungeScreen loungeScreen; + int index = 0; + + OsuScreen currentScreen = new TestMultiplayerScreen(index); + Children = new Drawable[] { - loungeScreen = new LoungeScreen(null) - { - Padding = new MarginPadding { Top = Header.HEIGHT }, - }, - new Header(loungeScreen), + currentScreen, + new Header(currentScreen) }; + + AddStep("push multi screen", () => currentScreen.Push(currentScreen = new TestMultiplayerScreen(++index))); + } + + private class TestMultiplayerScreen : OsuScreen, IMultiplayerScreen + { + private readonly int index; + + public string ShortTitle => $"Screen {index}"; + + public TestMultiplayerScreen(int index) + { + this.index = index; + } + + public override string ToString() => ShortTitle; } } } diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 570db11d50..849be44f4f 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -103,7 +103,8 @@ namespace osu.Game.Screens.Multi private class HeaderBreadcrumbControl : ScreenBreadcrumbControl { - public HeaderBreadcrumbControl(Screen initialScreen) : base(initialScreen) + public HeaderBreadcrumbControl(Screen initialScreen) + : base(initialScreen) { } From 09d7dc73dc043240e33c4136bafd55353fa9420e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:38:46 +0900 Subject: [PATCH 234/355] Allow channel manager and osugame to be null --- osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs | 4 ++-- osu.Game/Screens/Multi/Match/MatchScreen.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs index ecb7b86fb4..0d7221754f 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Multi.Match.Components { private readonly Room room; - [Resolved] + [Resolved(CanBeNull = true)] private ChannelManager channelManager { get; set; } public MatchChatDisplay(Room room) @@ -30,7 +30,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void updateChannel() { if (room.RoomID.Value != null) - Channel.Value = channelManager.JoinChannel(new Channel { Id = room.ChannelId, Type = ChannelType.Multiplayer, Name = $"#mp_{room.RoomID}" }); + Channel.Value = channelManager?.JoinChannel(new Channel { Id = room.ChannelId, Type = ChannelType.Multiplayer, Name = $"#mp_{room.RoomID}" }); } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 9a5950417b..72803c20a0 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Multi.Match [Resolved] private BeatmapManager beatmapManager { get; set; } - [Resolved] + [Resolved(CanBeNull = true)] private OsuGame game { get; set; } [Resolved(CanBeNull = true)] @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Multi.Match // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID); - game.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); + game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); } private void setMods(IEnumerable mods) @@ -133,7 +133,7 @@ namespace osu.Game.Screens.Multi.Match if (ruleset == null) return; - game.ForcefullySetRuleset(ruleset); + game?.ForcefullySetRuleset(ruleset); } private void addPlaylistItem(PlaylistItem item) From b82bb0ea281f2851c39b960f3affc436563267d0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:40:10 +0900 Subject: [PATCH 235/355] Mate RoomSettingsOverlay fill height --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 72803c20a0..927b786ab5 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -88,11 +88,7 @@ namespace osu.Game.Screens.Multi.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Components.Header.HEIGHT }, - Child = settings = new RoomSettingsOverlay(room) - { - RelativeSizeAxes = Axes.Both, - Height = 0.9f, - }, + Child = settings = new RoomSettingsOverlay(room) { RelativeSizeAxes = Axes.Both }, }, }; From 870d843fff7a229e18edb03aaf07f5d078d81b27 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 14:40:55 +0900 Subject: [PATCH 236/355] Fix username not displaying correctly in overlay --- osu.Game/Overlays/Profile/ProfileHeader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 3c7fe0b1eb..23739d8ad1 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -115,7 +115,7 @@ namespace osu.Game.Overlays.Profile Y = -48, Children = new Drawable[] { - new OsuSpriteText + usernameText = new OsuSpriteText { Text = user.Username, Font = @"Exo2.0-RegularItalic", @@ -317,6 +317,8 @@ namespace osu.Game.Overlays.Profile levelBadge.Texture = textures.Get(@"Profile/levelbadge"); } + private readonly OsuSpriteText usernameText; + private User user; public User User @@ -344,6 +346,8 @@ namespace osu.Game.Overlays.Profile if (user.IsSupporter) SupporterTag.Show(); + usernameText.Text = user.Username; + if (!string.IsNullOrEmpty(user.Colour)) { colourBar.Colour = OsuColour.FromHex(user.Colour); From e657f13c1539fa6deace5405f61a4b1df12e4728 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Dec 2018 19:51:27 +0900 Subject: [PATCH 237/355] Separate out Leaderboard into BeatmapLeaderboard --- osu.Game.Tests/Visual/TestCaseLeaderboard.cs | 5 +- .../Online/API/Requests/GetScoresRequest.cs | 6 +- .../Leaderboards/DrawableRank.cs | 4 +- .../Leaderboards/Leaderboard.cs | 113 +++++------------- .../Leaderboards/LeaderboardScore.cs | 79 +++++++----- .../Leaderboards/MessagePlaceholder.cs | 2 +- .../Leaderboards/Placeholder.cs | 2 +- .../Leaderboards/PlaceholderState.cs | 2 +- .../RetrievalFailurePlaceholder.cs | 2 +- .../BeatmapSet/Scores/DrawableScore.cs | 2 +- .../BeatmapSet/Scores/DrawableTopScore.cs | 2 +- .../Sections/Ranks/DrawableProfileScore.cs | 2 +- .../Sections/Recent/DrawableRecentActivity.cs | 2 +- .../Screens/Ranking/ResultsPageRanking.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 2 +- osu.Game/Screens/Select/BeatmapDetailArea.cs | 6 +- .../Select/Leaderboards/BeatmapLeaderboard.cs | 87 ++++++++++++++ ...ardScope.cs => BeatmapLeaderboardScope.cs} | 2 +- .../Leaderboards/BeatmapLeaderboardScore.cs | 34 ++++++ 19 files changed, 224 insertions(+), 132 deletions(-) rename osu.Game/{Screens/Select => Online}/Leaderboards/DrawableRank.cs (96%) rename osu.Game/{Screens/Select => Online}/Leaderboards/Leaderboard.cs (76%) rename osu.Game/{Screens/Select => Online}/Leaderboards/LeaderboardScore.cs (87%) rename osu.Game/{Screens/Select => Online}/Leaderboards/MessagePlaceholder.cs (94%) rename osu.Game/{Screens/Select => Online}/Leaderboards/Placeholder.cs (94%) rename osu.Game/{Screens/Select => Online}/Leaderboards/PlaceholderState.cs (88%) rename osu.Game/{Screens/Select => Online}/Leaderboards/RetrievalFailurePlaceholder.cs (97%) create mode 100644 osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs rename osu.Game/Screens/Select/Leaderboards/{LeaderboardScope.cs => BeatmapLeaderboardScope.cs} (87%) create mode 100644 osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index f7630f0902..10d7eaee8a 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using osuTK; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Scoring; @@ -36,7 +37,7 @@ namespace osu.Game.Tests.Visual Origin = Anchor.Centre, Anchor = Anchor.Centre, Size = new Vector2(550f, 450f), - Scope = LeaderboardScope.Global, + Scope = BeatmapLeaderboardScope.Global, }); AddStep(@"New Scores", newScores); @@ -275,7 +276,7 @@ namespace osu.Game.Tests.Visual }; } - private class FailableLeaderboard : Leaderboard + private class FailableLeaderboard : BeatmapLeaderboard { public void SetRetrievalState(PlaceholderState state) { diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 2751dd956b..ae2c7dc269 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -13,15 +13,15 @@ namespace osu.Game.Online.API.Requests public class GetScoresRequest : APIRequest { private readonly BeatmapInfo beatmap; - private readonly LeaderboardScope scope; + private readonly BeatmapLeaderboardScope scope; private readonly RulesetInfo ruleset; - public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, LeaderboardScope scope = LeaderboardScope.Global) + public GetScoresRequest(BeatmapInfo beatmap, RulesetInfo ruleset, BeatmapLeaderboardScope scope = BeatmapLeaderboardScope.Global) { if (!beatmap.OnlineBeatmapID.HasValue) throw new InvalidOperationException($"Cannot lookup a beatmap's scores without having a populated {nameof(BeatmapInfo.OnlineBeatmapID)}."); - if (scope == LeaderboardScope.Local) + if (scope == BeatmapLeaderboardScope.Local) throw new InvalidOperationException("Should not attempt to request online scores for a local scoped leaderboard"); this.beatmap = beatmap; diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs similarity index 96% rename from osu.Game/Screens/Select/Leaderboards/DrawableRank.cs rename to osu.Game/Online/Leaderboards/DrawableRank.cs index 3258a62adf..1c68c64180 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -2,14 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Extensions; using osu.Game.Scoring; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public class DrawableRank : Container { diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs similarity index 76% rename from osu.Game/Screens/Select/Leaderboards/Leaderboard.cs rename to osu.Game/Online/Leaderboards/Leaderboard.cs index a65cc6f096..8e83c8ad5a 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -3,38 +3,30 @@ using System; using System.Collections.Generic; -using osuTK; -using osuTK.Graphics; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; -using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; 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; +using osu.Game.Screens.Select.Leaderboards; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { - public class Leaderboard : Container + public abstract class Leaderboard : Container { private const double fade_duration = 300; private readonly ScrollContainer scrollContainer; private readonly Container placeholderContainer; - private FillFlowContainer scrollFlow; - - private readonly IBindable ruleset = new Bindable(); - - public Action ScoreSelected; + private FillFlowContainer> scrollFlow; private readonly LoadingAnimation loading; @@ -42,9 +34,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 @@ -64,13 +56,13 @@ namespace osu.Game.Screens.Select.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - var flow = scrollFlow = new FillFlowContainer + var flow = scrollFlow = new FillFlowContainer> { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 5f), Padding = new MarginPadding { Top = 10, Bottom = 5 }, - ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) }) + ChildrenEnumerable = scores.Select((s, index) => CreateScoreVisualiser(s, index + 1)) }; // schedule because we may not be loaded yet (LoadComponentAsync complains). @@ -96,18 +88,18 @@ namespace osu.Game.Screens.Select.Leaderboards } } - private LeaderboardScope scope; + private TScope scope; - public LeaderboardScope Scope + public TScope Scope { get { return scope; } set { - if (value == scope) + if (value.Equals(scope)) return; scope = value; - updateScores(); + UpdateScores(); } } @@ -137,7 +129,7 @@ namespace osu.Game.Screens.Select.Leaderboards case PlaceholderState.NetworkFailure: replacePlaceholder(new RetrievalFailurePlaceholder { - OnRetry = updateScores, + OnRetry = UpdateScores, }); break; case PlaceholderState.Unavailable: @@ -159,7 +151,7 @@ namespace osu.Game.Screens.Select.Leaderboards } } - public Leaderboard() + protected Leaderboard() { Children = new Drawable[] { @@ -177,36 +169,14 @@ namespace osu.Game.Screens.Select.Leaderboards } private APIAccess api; - private BeatmapInfo beatmap; - - [Resolved] - private ScoreManager scoreManager { get; set; } private ScheduledDelegate pendingUpdateScores; - public BeatmapInfo Beatmap - { - get { return beatmap; } - set - { - if (beatmap == value) - return; - - beatmap = value; - Scores = null; - - updateScores(); - } - } - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, IBindable parentRuleset) + [BackgroundDependencyLoader(true)] + private void load(APIAccess api) { this.api = api; - ruleset.BindTo(parentRuleset); - ruleset.ValueChanged += _ => updateScores(); - if (api != null) api.OnStateChange += handleApiStateChange; } @@ -219,21 +189,17 @@ namespace osu.Game.Screens.Select.Leaderboards api.OnStateChange -= handleApiStateChange; } - public void RefreshScores() => updateScores(); + public void RefreshScores() => UpdateScores(); - private GetScoresRequest getScoresRequest; + private APIRequest getScoresRequest; private void handleApiStateChange(APIState oldState, APIState newState) { - if (Scope == LeaderboardScope.Local) - // No need to respond to API state change while current scope is local - return; - if (newState == APIState.Online) - updateScores(); + UpdateScores(); } - private void updateScores() + protected void UpdateScores() { // don't display any scores or placeholder until the first Scores_Set has been called. // this avoids scope changes flickering a "no scores" placeholder before initialisation of song select is finished. @@ -245,40 +211,23 @@ namespace osu.Game.Screens.Select.Leaderboards pendingUpdateScores?.Cancel(); pendingUpdateScores = Schedule(() => { - if (Scope == LeaderboardScope.Local) - { - Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray(); - PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; - return; - } - - if (Beatmap?.OnlineBeatmapID == null) - { - PlaceholderState = PlaceholderState.Unavailable; - return; - } - if (api?.IsLoggedIn != true) { PlaceholderState = PlaceholderState.NotLoggedIn; return; } - if (Scope != LeaderboardScope.Global && !api.LocalUser.Value.IsSupporter) - { - PlaceholderState = PlaceholderState.NotSupporter; - return; - } - PlaceholderState = PlaceholderState.Retrieving; loading.Show(); - getScoresRequest = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope); - getScoresRequest.Success += r => Schedule(() => + getScoresRequest = FetchScores(scores => Schedule(() => { - Scores = r.Scores; + Scores = scores; PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; - }); + })); + + if (getScoresRequest == null) + return; getScoresRequest.Failure += e => Schedule(() => { @@ -292,6 +241,8 @@ namespace osu.Game.Screens.Select.Leaderboards }); } + protected abstract APIRequest FetchScores(Action> scoresCallback); + private Placeholder currentPlaceholder; private void replacePlaceholder(Placeholder placeholder) @@ -344,5 +295,7 @@ namespace osu.Game.Screens.Select.Leaderboards } } } + + protected abstract LeaderboardScore CreateScoreVisualiser(TScoreModel model, int index); } } diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs similarity index 87% rename from osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs rename to osu.Game/Online/Leaderboards/LeaderboardScore.cs index 1ba529c0bf..63352754a8 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -1,9 +1,8 @@ // 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 osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -14,47 +13,60 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { - public class LeaderboardScore : OsuClickableContainer + public static class LeaderboardScore { - public static readonly float HEIGHT = 60; + public const float HEIGHT = 60; + } + public abstract class LeaderboardScore : OsuClickableContainer + { public readonly int RankPosition; - public readonly ScoreInfo Score; private const float corner_radius = 5; private const float edge_margin = 5; private const float background_alpha = 0.25f; private const float rank_width = 30; + protected Container RankContainer { get; private set; } + + private readonly TScoreModel score; + private Box background; private Container content; private Drawable avatar; - private DrawableRank scoreRank; + private Drawable scoreRank; private OsuSpriteText nameLabel; private GlowingSpriteText scoreLabel; - private ScoreComponentLabel maxCombo; - private ScoreComponentLabel accuracy; private Container flagBadgeContainer; private FillFlowContainer modsContainer; - public LeaderboardScore(ScoreInfo score, int rank) + private List statisticsLabels; + + protected LeaderboardScore(TScoreModel score, int rank) { - Score = score; + this.score = score; RankPosition = rank; RelativeSizeAxes = Axes.X; - Height = HEIGHT; + Height = LeaderboardScore.HEIGHT; } [BackgroundDependencyLoader] private void load() { + var user = GetUser(score); + + statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s.icon, s.value, s.name)).ToList(); + Children = new Drawable[] { new Container @@ -102,7 +114,7 @@ namespace osu.Game.Screens.Select.Leaderboards Children = new[] { avatar = new DelayedLoadWrapper( - new Avatar(Score.User) + new Avatar(user) { RelativeSizeAxes = Axes.Both, CornerRadius = corner_radius, @@ -117,18 +129,18 @@ namespace osu.Game.Screens.Select.Leaderboards }) { RelativeSizeAxes = Axes.None, - Size = new Vector2(HEIGHT - edge_margin * 2, HEIGHT - edge_margin * 2), + Size = new Vector2(LeaderboardScore.HEIGHT - edge_margin * 2, LeaderboardScore.HEIGHT - edge_margin * 2), }, new Container { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, - Position = new Vector2(HEIGHT - edge_margin, 0f), + Position = new Vector2(LeaderboardScore.HEIGHT - edge_margin, 0f), Children = new Drawable[] { nameLabel = new OsuSpriteText { - Text = Score.User.Username, + Text = user.Username, Font = @"Exo2.0-BoldItalic", TextSize = 23, }, @@ -149,7 +161,7 @@ namespace osu.Game.Screens.Select.Leaderboards Masking = true, Children = new Drawable[] { - new DrawableFlag(Score.User?.Country) + new DrawableFlag(user.Country) { Width = 30, RelativeSizeAxes = Axes.Y, @@ -164,11 +176,7 @@ namespace osu.Game.Screens.Select.Leaderboards Direction = FillDirection.Horizontal, Spacing = new Vector2(10f, 0f), 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"), - }, + Children = statisticsLabels }, }, }, @@ -183,17 +191,17 @@ 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")), - new Container + scoreLabel = new GlowingSpriteText(GetTotalScore(score).ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + RankContainer = new Container { Size = new Vector2(40f, 20f), Children = new[] { - scoreRank = new DrawableRank(Score.Rank) + scoreRank = new DrawableRank(GetRank(score)) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(40f), + Size = new Vector2(40f) }, }, }, @@ -205,7 +213,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 = GetMods(score).Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, }, @@ -216,7 +224,7 @@ namespace osu.Game.Screens.Select.Leaderboards public override void Show() { - foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, maxCombo, accuracy, modsContainer }) + foreach (var d in new[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, modsContainer }.Concat(statisticsLabels)) d.FadeOut(); Alpha = 0; @@ -243,7 +251,7 @@ namespace osu.Game.Screens.Select.Leaderboards using (BeginDelayedSequence(50, true)) { - var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, }; + var drawables = new Drawable[] { flagBadgeContainer, modsContainer }.Concat(statisticsLabels).ToArray(); for (int i = 0; i < drawables.Length; i++) drawables[i].FadeIn(100 + i * 50); } @@ -263,6 +271,16 @@ namespace osu.Game.Screens.Select.Leaderboards base.OnHoverLost(e); } + protected abstract User GetUser(TScoreModel model); + + protected abstract IEnumerable GetMods(TScoreModel model); + + protected abstract IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(TScoreModel model); + + protected abstract int GetTotalScore(TScoreModel model); + + protected abstract ScoreRank GetRank(TScoreModel model); + private class GlowingSpriteText : Container { public GlowingSpriteText(string text, string font, int textSize, Color4 textColour, Color4 glowColour) @@ -324,8 +342,7 @@ namespace osu.Game.Screens.Select.Leaderboards public ScoreComponentLabel(FontAwesome icon, string value, string name) { this.name = name; - AutoSizeAxes = Axes.Y; - Width = 60; + AutoSizeAxes = Axes.Both; Child = content = new FillFlowContainer { diff --git a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs similarity index 94% rename from osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs rename to osu.Game/Online/Leaderboards/MessagePlaceholder.cs index f01a55b662..ea92836e6e 100644 --- a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public class MessagePlaceholder : Placeholder { diff --git a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs b/osu.Game/Online/Leaderboards/Placeholder.cs similarity index 94% rename from osu.Game/Screens/Select/Leaderboards/Placeholder.cs rename to osu.Game/Online/Leaderboards/Placeholder.cs index 468b43e54f..4994ce0e99 100644 --- a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs +++ b/osu.Game/Online/Leaderboards/Placeholder.cs @@ -5,7 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public abstract class Placeholder : OsuTextFlowContainer, IEquatable { diff --git a/osu.Game/Screens/Select/Leaderboards/PlaceholderState.cs b/osu.Game/Online/Leaderboards/PlaceholderState.cs similarity index 88% rename from osu.Game/Screens/Select/Leaderboards/PlaceholderState.cs rename to osu.Game/Online/Leaderboards/PlaceholderState.cs index 33a56540f3..504b03432f 100644 --- a/osu.Game/Screens/Select/Leaderboards/PlaceholderState.cs +++ b/osu.Game/Online/Leaderboards/PlaceholderState.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 -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public enum PlaceholderState { diff --git a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs similarity index 97% rename from osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs rename to osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs index 66a7793f7c..7fed40ed1a 100644 --- a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osuTK; -namespace osu.Game.Screens.Select.Leaderboards +namespace osu.Game.Online.Leaderboards { public class RetrievalFailurePlaceholder : Placeholder { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index f643e130aa..89416c1098 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -10,11 +10,11 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; 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.Screens.Select.Leaderboards; using osu.Game.Users; namespace osu.Game.Overlays.BeatmapSet.Scores diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 643839fa88..6259d85bee 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -12,12 +12,12 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; 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; namespace osu.Game.Overlays.BeatmapSet.Scores diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 1c39cb309c..18aa684664 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -6,8 +6,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Select.Leaderboards; using osu.Game.Rulesets.UI; using osu.Game.Scoring; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index fefb289d17..8b4fb1a229 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -10,7 +10,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; -using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Online.Leaderboards; namespace osu.Game.Overlays.Profile.Sections.Recent { diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index c5a5cc6ad9..3a75daaf60 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Ranking Colour = colours.GrayE, RelativeSizeAxes = Axes.Both, }, - new Leaderboard + new BeatmapLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 62103314e1..0774a63e98 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -19,11 +19,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; -using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions; using osu.Framework.Localisation; +using osu.Game.Online.Leaderboards; using osu.Game.Scoring; namespace osu.Game.Screens.Ranking diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index a6fbd201d0..c5c4960ed4 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select protected override Container Content => content; public readonly BeatmapDetails Details; - public readonly Leaderboard Leaderboard; + public readonly BeatmapLeaderboard Leaderboard; private WorkingBeatmap beatmap; public WorkingBeatmap Beatmap @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Select default: Details.Hide(); - Leaderboard.Scope = (LeaderboardScope)tab - 1; + Leaderboard.Scope = (BeatmapLeaderboardScope)tab - 1; Leaderboard.Show(); break; } @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Select Alpha = 0, Margin = new MarginPadding { Top = details_padding }, }, - Leaderboard = new Leaderboard + Leaderboard = new BeatmapLeaderboard { RelativeSizeAxes = Axes.Both, } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs new file mode 100644 index 0000000000..b0cfad314c --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -0,0 +1,87 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets; +using osu.Game.Scoring; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public class BeatmapLeaderboard : Leaderboard + { + public Action ScoreSelected; + + private BeatmapInfo beatmap; + + public BeatmapInfo Beatmap + { + get { return beatmap; } + set + { + if (beatmap == value) + return; + + beatmap = value; + Scores = null; + + UpdateScores(); + } + } + + [Resolved] + private ScoreManager scoreManager { get; set; } + + [Resolved] + private IBindable ruleset { get; set; } + + [Resolved] + private APIAccess api { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + ruleset.ValueChanged += _ => UpdateScores(); + } + + protected override APIRequest FetchScores(Action> scoresCallback) + { + if (Scope == BeatmapLeaderboardScope.Local) + { + Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray(); + PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; + return null; + } + + if (Beatmap?.OnlineBeatmapID == null) + { + PlaceholderState = PlaceholderState.Unavailable; + return null; + } + + if (Scope != BeatmapLeaderboardScope.Global && !api.LocalUser.Value.IsSupporter) + { + PlaceholderState = PlaceholderState.NotSupporter; + return null; + } + + var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope); + + req.Success += r => scoresCallback?.Invoke(r.Scores); + + return req; + } + + protected override LeaderboardScore CreateScoreVisualiser(ScoreInfo model, int index) => new BeatmapLeaderboardScore(model, index) + { + Action = () => ScoreSelected?.Invoke(model) + }; + } +} diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs similarity index 87% rename from osu.Game/Screens/Select/Leaderboards/LeaderboardScope.cs rename to osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index 761f53a5e8..39d9580792 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs @@ -3,7 +3,7 @@ namespace osu.Game.Screens.Select.Leaderboards { - public enum LeaderboardScope + public enum BeatmapLeaderboardScope { Local, Country, diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs new file mode 100644 index 0000000000..098fff4052 --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.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 osu.Game.Graphics; +using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public class BeatmapLeaderboardScore : LeaderboardScore + { + public BeatmapLeaderboardScore(ScoreInfo score, int rank) + : base(score, rank) + { + } + + protected override User GetUser(ScoreInfo model) => model.User; + + protected override IEnumerable GetMods(ScoreInfo model) => model.Mods; + + protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(ScoreInfo model) => new[] + { + (FontAwesome.fa_link, model.MaxCombo.ToString(), "Max Combo"), + (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy") + }; + + protected override int GetTotalScore(ScoreInfo model) => model.TotalScore; + + protected override ScoreRank GetRank(ScoreInfo model) => model.Rank; + } +} From 23259b295cb5044be6923961d2e024d5b98fc895 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 14:45:35 +0900 Subject: [PATCH 238/355] Remove unnecessary using --- osu.Game/Online/Leaderboards/Leaderboard.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 8e83c8ad5a..83cc289bc1 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -13,7 +13,6 @@ using osu.Framework.Threading; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; -using osu.Game.Screens.Select.Leaderboards; using osuTK; using osuTK.Graphics; From 34fc740e1f72e6ec4b8f5865d0e2f008d2973a02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 14:48:15 +0900 Subject: [PATCH 239/355] Implement testcase for room settings --- .../Visual/TestCaseMatchSettingsOverlay.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs new file mode 100644 index 0000000000..dd5d242f56 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Match.Components; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMatchSettingsOverlay : OsuTestCase + { + public TestCaseMatchSettingsOverlay() + { + Child = new RoomSettingsOverlay(new Room()) + { + RelativeSizeAxes = Axes.Both, + State = Visibility.Visible + }; + } + } +} From 6afd2f72634aee31a1583e012ef7cf2f69b0e213 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 15:00:35 +0900 Subject: [PATCH 240/355] Adjust styling of disabled settings --- .../Visual/TestCaseMatchSettingsOverlay.cs | 7 +++++++ .../Multi/Components/DisableableTabControl.cs | 15 ++++----------- .../Multi/Match/Components/RoomSettingsOverlay.cs | 9 +++++++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index dd5d242f56..fede2f509f 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.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 System; +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; @@ -10,6 +12,11 @@ namespace osu.Game.Tests.Visual { public class TestCaseMatchSettingsOverlay : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RoomSettingsOverlay) + }; + public TestCaseMatchSettingsOverlay() { Child = new RoomSettingsOverlay(new Room()) diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs index fdc2fd578d..dc765832db 100644 --- a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -4,39 +4,32 @@ using osu.Framework.Configuration; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osuTK.Graphics; namespace osu.Game.Screens.Multi.Components { public abstract class DisableableTabControl : TabControl { - public readonly BindableBool ReadOnly = new BindableBool(); + public readonly BindableBool Enabled = new BindableBool(); protected override void AddTabItem(TabItem tab, bool addToDropdown = true) { if (tab is DisableableTabItem disableable) - disableable.ReadOnly.BindTo(ReadOnly); + disableable.Enabled.BindTo(Enabled); base.AddTabItem(tab, addToDropdown); } protected abstract class DisableableTabItem : TabItem { - public readonly BindableBool ReadOnly = new BindableBool(); + public readonly BindableBool Enabled = new BindableBool(); protected DisableableTabItem(T value) : base(value) { - ReadOnly.BindValueChanged(updateReadOnly); - } - - private void updateReadOnly(bool readOnly) - { - Colour = readOnly ? Color4.Gray : Color4.White; } protected override bool OnClick(ClickEvent e) { - if (ReadOnly) + if (!Enabled) return true; return base.OnClick(e); } diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index 65e1f068a8..db29722025 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -22,6 +22,7 @@ namespace osu.Game.Screens.Multi.Match.Components { private const float transition_duration = 350; private const float field_padding = 45; + private const float disabled_alpha = 0.2f; private readonly RoomBindings bindings = new RoomBindings(); @@ -82,10 +83,12 @@ namespace osu.Game.Screens.Multi.Match.Components }, new Section("ROOM VISIBILITY") { + Alpha = disabled_alpha, Child = AvailabilityPicker = new RoomAvailabilityPicker(), }, new Section("GAME TYPE") { + Alpha = disabled_alpha, Child = new FillFlowContainer { AutoSizeAxes = Axes.Y, @@ -116,6 +119,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new Section("MAX PARTICIPANTS") { + Alpha = disabled_alpha, Child = MaxParticipantsField = new SettingsNumberTextBox { RelativeSizeAxes = Axes.X, @@ -146,6 +150,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, new Section("PASSWORD (OPTIONAL)") { + Alpha = disabled_alpha, Child = PasswordField = new SettingsPasswordTextBox { RelativeSizeAxes = Axes.X, @@ -199,8 +204,8 @@ namespace osu.Game.Screens.Multi.Match.Components MaxParticipantsField.ReadOnly = true; PasswordField.ReadOnly = true; - AvailabilityPicker.ReadOnly.Value = true; - TypePicker.ReadOnly.Value = true; + AvailabilityPicker.Enabled.Value = false; + TypePicker.Enabled.Value = false; ApplyButton.Enabled.Value = false; } From 3570c35d7fd7495ff52d8e502a98a1e6e247a15f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 15:17:35 +0900 Subject: [PATCH 241/355] Make RoomScore derive ScoreInfo --- osu.Game/Scoring/ScoreInfo.cs | 5 +++-- .../Multi/Match/Components/MatchLeaderboard.cs | 14 +------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index a689590819..8ffade1e2b 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -98,8 +98,9 @@ namespace osu.Game.Scoring } } - [JsonIgnore] - public User User; + [NotMapped] + [JsonProperty("user")] + public User User { get; set; } [JsonIgnore] [Column("User")] diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 4b09349be5..2fbeea4377 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -102,20 +102,8 @@ namespace osu.Game.Screens.Multi.Match.Components Overall } - public class RoomScore + public class RoomScore : ScoreInfo { - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("accuracy")] - public double Accuracy { get; set; } - - [JsonProperty("total_score")] - public int TotalScore { get; set; } - - [JsonProperty("pp")] - public double? PP { get; set; } - [JsonProperty("attempts")] public int TotalAttempts { get; set; } From 787e65c3c58bc8788c373de8e5ca5a4cd6007993 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 15:20:35 +0900 Subject: [PATCH 242/355] Reduce generic-ness --- osu.Game/Online/Leaderboards/Leaderboard.cs | 16 ++--- .../Online/Leaderboards/LeaderboardScore.cs | 68 ++++++++++--------- .../Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- .../Leaderboards/BeatmapLeaderboardScore.cs | 34 ---------- 4 files changed, 46 insertions(+), 74 deletions(-) delete mode 100644 osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 83cc289bc1..d9d78245bb 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -18,14 +18,14 @@ using osuTK.Graphics; namespace osu.Game.Online.Leaderboards { - public abstract class Leaderboard : Container + public abstract class Leaderboard : Container { private const double fade_duration = 300; private readonly ScrollContainer scrollContainer; private readonly Container placeholderContainer; - private FillFlowContainer> scrollFlow; + private FillFlowContainer scrollFlow; private readonly LoadingAnimation loading; @@ -33,9 +33,9 @@ namespace osu.Game.Online.Leaderboards private bool scoresLoadedOnce; - private IEnumerable scores; + private IEnumerable scores; - public IEnumerable Scores + public IEnumerable Scores { get { return scores; } set @@ -55,13 +55,13 @@ namespace osu.Game.Online.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - var flow = scrollFlow = new FillFlowContainer> + var flow = scrollFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 5f), Padding = new MarginPadding { Top = 10, Bottom = 5 }, - ChildrenEnumerable = scores.Select((s, index) => CreateScoreVisualiser(s, index + 1)) + ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)) }; // schedule because we may not be loaded yet (LoadComponentAsync complains). @@ -240,7 +240,7 @@ namespace osu.Game.Online.Leaderboards }); } - protected abstract APIRequest FetchScores(Action> scoresCallback); + protected abstract APIRequest FetchScores(Action> scoresCallback); private Placeholder currentPlaceholder; @@ -295,6 +295,6 @@ namespace osu.Game.Online.Leaderboards } } - protected abstract LeaderboardScore CreateScoreVisualiser(TScoreModel model, int index); + protected abstract LeaderboardScore CreateDrawableScore(ScoreInfo model, int index); } } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 63352754a8..8269e02847 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -13,7 +13,6 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users; @@ -22,15 +21,12 @@ using osuTK.Graphics; namespace osu.Game.Online.Leaderboards { - public static class LeaderboardScore - { - public const float HEIGHT = 60; - } - - public abstract class LeaderboardScore : OsuClickableContainer + public class LeaderboardScore : OsuClickableContainer { public readonly int RankPosition; + public const float HEIGHT = 60; + private const float corner_radius = 5; private const float edge_margin = 5; private const float background_alpha = 0.25f; @@ -38,7 +34,7 @@ namespace osu.Game.Online.Leaderboards protected Container RankContainer { get; private set; } - private readonly TScoreModel score; + private readonly ScoreInfo score; private Box background; private Container content; @@ -51,21 +47,27 @@ namespace osu.Game.Online.Leaderboards private List statisticsLabels; - protected LeaderboardScore(TScoreModel score, int rank) + public LeaderboardScore(ScoreInfo score, int rank) { this.score = score; RankPosition = rank; RelativeSizeAxes = Axes.X; - Height = LeaderboardScore.HEIGHT; + Height = HEIGHT; } + protected virtual IEnumerable GetStatistics(ScoreInfo model) => new[] + { + new LeaderboardScoreStatistic(FontAwesome.fa_link, "Max Combo", model.MaxCombo.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)) + }; + [BackgroundDependencyLoader] private void load() { - var user = GetUser(score); + var user = score.User; - statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s.icon, s.value, s.name)).ToList(); + statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s)).ToList(); Children = new Drawable[] { @@ -129,13 +131,13 @@ namespace osu.Game.Online.Leaderboards }) { RelativeSizeAxes = Axes.None, - Size = new Vector2(LeaderboardScore.HEIGHT - edge_margin * 2, LeaderboardScore.HEIGHT - edge_margin * 2), + Size = new Vector2(HEIGHT - edge_margin * 2, HEIGHT - edge_margin * 2), }, new Container { RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, - Position = new Vector2(LeaderboardScore.HEIGHT - edge_margin, 0f), + Position = new Vector2(HEIGHT - edge_margin, 0f), Children = new Drawable[] { nameLabel = new OsuSpriteText @@ -191,13 +193,13 @@ namespace osu.Game.Online.Leaderboards Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - scoreLabel = new GlowingSpriteText(GetTotalScore(score).ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), RankContainer = new Container { Size = new Vector2(40f, 20f), Children = new[] { - scoreRank = new DrawableRank(GetRank(score)) + scoreRank = new DrawableRank(score.Rank) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -213,7 +215,7 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.BottomRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = GetMods(score).Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) + ChildrenEnumerable = score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, }, @@ -271,16 +273,6 @@ namespace osu.Game.Online.Leaderboards base.OnHoverLost(e); } - protected abstract User GetUser(TScoreModel model); - - protected abstract IEnumerable GetMods(TScoreModel model); - - protected abstract IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(TScoreModel model); - - protected abstract int GetTotalScore(TScoreModel model); - - protected abstract ScoreRank GetRank(TScoreModel model); - private class GlowingSpriteText : Container { public GlowingSpriteText(string text, string font, int textSize, Color4 textColour, Color4 glowColour) @@ -339,9 +331,9 @@ namespace osu.Game.Online.Leaderboards public string TooltipText => name; - public ScoreComponentLabel(FontAwesome icon, string value, string name) + public ScoreComponentLabel(LeaderboardScoreStatistic statistic) { - this.name = name; + name = statistic.Name; AutoSizeAxes = Axes.Both; Child = content = new FillFlowContainer @@ -373,11 +365,11 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.Centre, Size = new Vector2(icon_size - 6), Colour = OsuColour.FromHex(@"a4edff"), - Icon = icon, + Icon = statistic.Icon, }, }, }, - new GlowingSpriteText(value, @"Exo2.0-Bold", 17, Color4.White, OsuColour.FromHex(@"83ccfa")) + new GlowingSpriteText(statistic.Value, @"Exo2.0-Bold", 17, Color4.White, OsuColour.FromHex(@"83ccfa")) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -386,5 +378,19 @@ namespace osu.Game.Online.Leaderboards }; } } + + public class LeaderboardScoreStatistic + { + public FontAwesome Icon; + public string Value; + public string Name; + + public LeaderboardScoreStatistic(FontAwesome icon, string name, string value) + { + Icon = icon; + Name = name; + Value = value; + } + } } } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index b0cfad314c..9f8726c86a 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Select.Leaderboards return req; } - protected override LeaderboardScore CreateScoreVisualiser(ScoreInfo model, int index) => new BeatmapLeaderboardScore(model, index) + protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index) { Action = () => ScoreSelected?.Invoke(model) }; diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs deleted file mode 100644 index 098fff4052..0000000000 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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.Game.Graphics; -using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; -using osu.Game.Users; - -namespace osu.Game.Screens.Select.Leaderboards -{ - public class BeatmapLeaderboardScore : LeaderboardScore - { - public BeatmapLeaderboardScore(ScoreInfo score, int rank) - : base(score, rank) - { - } - - protected override User GetUser(ScoreInfo model) => model.User; - - protected override IEnumerable GetMods(ScoreInfo model) => model.Mods; - - protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(ScoreInfo model) => new[] - { - (FontAwesome.fa_link, model.MaxCombo.ToString(), "Max Combo"), - (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy") - }; - - protected override int GetTotalScore(ScoreInfo model) => model.TotalScore; - - protected override ScoreRank GetRank(ScoreInfo model) => model.Rank; - } -} From 52c6d5bfd418dbc3f6ab1e203f98b9b04d2edeb4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 15:23:32 +0900 Subject: [PATCH 243/355] Move protected method down --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 8269e02847..0c64105d5c 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -56,12 +56,6 @@ namespace osu.Game.Online.Leaderboards Height = HEIGHT; } - protected virtual IEnumerable GetStatistics(ScoreInfo model) => new[] - { - new LeaderboardScoreStatistic(FontAwesome.fa_link, "Max Combo", model.MaxCombo.ToString()), - new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)) - }; - [BackgroundDependencyLoader] private void load() { @@ -261,6 +255,12 @@ namespace osu.Game.Online.Leaderboards } } + protected virtual IEnumerable GetStatistics(ScoreInfo model) => new[] + { + new LeaderboardScoreStatistic(FontAwesome.fa_link, "Max Combo", model.MaxCombo.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)) + }; + protected override bool OnHover(HoverEvent e) { background.FadeTo(0.5f, 300, Easing.OutQuint); From ac0e6f8d42eface1fead880b79b40cd8db1833ff Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 15:35:22 +0900 Subject: [PATCH 244/355] Fix post-merge issues --- .../Match/Components/MatchLeaderboard.cs | 23 ++++--------- .../Leaderboards/BeatmapLeaderboardScore.cs | 34 ------------------- 2 files changed, 6 insertions(+), 51 deletions(-) delete mode 100644 osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 2fbeea4377..d6c7c28840 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -3,16 +3,13 @@ using System; using System.Collections.Generic; -using System.Linq; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.Leaderboards; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets.Mods; using osu.Game.Scoring; -using osu.Game.Users; namespace osu.Game.Screens.Multi.Match.Components { @@ -53,7 +50,7 @@ namespace osu.Game.Screens.Multi.Match.Components return req; } - protected override LeaderboardScore CreateScoreVisualiser(RoomScore model, int index) => new MatchLeaderboardScore(model, index); + protected override LeaderboardScore CreateDrawableScore(RoomScore model, int index) => new MatchLeaderboardScore(model, index); private class GetRoomScoresRequest : APIRequest> { @@ -68,7 +65,7 @@ namespace osu.Game.Screens.Multi.Match.Components } } - public class MatchLeaderboardScore : LeaderboardScore + public class MatchLeaderboardScore : LeaderboardScore { public MatchLeaderboardScore(RoomScore score, int rank) : base(score, rank) @@ -81,20 +78,12 @@ namespace osu.Game.Screens.Multi.Match.Components RankContainer.Alpha = 0; } - protected override User GetUser(RoomScore model) => model.User; - - protected override IEnumerable GetMods(RoomScore model) => Enumerable.Empty(); // Not implemented yet - - protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(RoomScore model) => new[] + protected override IEnumerable GetStatistics(ScoreInfo model) => new[] { - (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy"), - (FontAwesome.fa_refresh, model.TotalAttempts.ToString(), "Total Attempts"), - (FontAwesome.fa_check, model.CompletedAttempts.ToString(), "Completed Beatmaps"), + new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), + new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((RoomScore)model).TotalAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((RoomScore)model).CompletedAttempts.ToString()), }; - - protected override int GetTotalScore(RoomScore model) => model.TotalScore; - - protected override ScoreRank GetRank(RoomScore model) => ScoreRank.S; } public enum MatchLeaderboardScope diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs deleted file mode 100644 index 098fff4052..0000000000 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScore.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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.Game.Graphics; -using osu.Game.Online.Leaderboards; -using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; -using osu.Game.Users; - -namespace osu.Game.Screens.Select.Leaderboards -{ - public class BeatmapLeaderboardScore : LeaderboardScore - { - public BeatmapLeaderboardScore(ScoreInfo score, int rank) - : base(score, rank) - { - } - - protected override User GetUser(ScoreInfo model) => model.User; - - protected override IEnumerable GetMods(ScoreInfo model) => model.Mods; - - protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(ScoreInfo model) => new[] - { - (FontAwesome.fa_link, model.MaxCombo.ToString(), "Max Combo"), - (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy") - }; - - protected override int GetTotalScore(ScoreInfo model) => model.TotalScore; - - protected override ScoreRank GetRank(ScoreInfo model) => model.Rank; - } -} From daa6292e087366f2cdde87c804e641dad09fb6f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 21 Dec 2018 16:28:33 +0900 Subject: [PATCH 245/355] Split results screen to allow for extensibility --- osu.Game.Tests/Visual/TestCaseResults.cs | 8 ++-- osu.Game/Screens/Play/Player.cs | 3 +- osu.Game/Screens/Play/SoloResults.cs | 24 +++++++++++ .../RankingResultsPage.cs} | 11 ++--- .../Ranking/{ => Pages}/ResultsPage.cs | 2 +- .../ScoreResultsPage.cs} | 23 +++++----- osu.Game/Screens/Ranking/ResultMode.cs | 12 ------ osu.Game/Screens/Ranking/ResultModeButton.cs | 19 +++----- .../Screens/Ranking/ResultModeTabControl.cs | 7 +-- osu.Game/Screens/Ranking/Results.cs | 43 ++++++++----------- osu.Game/Screens/Ranking/Types/IResultType.cs | 15 +++++++ .../Ranking/Types/RankingResultType.cs | 26 +++++++++++ .../Screens/Ranking/Types/ScoreResultType.cs | 26 +++++++++++ osu.Game/Screens/Select/SongSelect.cs | 4 +- 14 files changed, 147 insertions(+), 76 deletions(-) create mode 100644 osu.Game/Screens/Play/SoloResults.cs rename osu.Game/Screens/Ranking/{ResultsPageRanking.cs => Pages/RankingResultsPage.cs} (83%) rename osu.Game/Screens/Ranking/{ => Pages}/ResultsPage.cs (98%) rename osu.Game/Screens/Ranking/{ResultsPageScore.cs => Pages/ScoreResultsPage.cs} (98%) delete mode 100644 osu.Game/Screens/Ranking/ResultMode.cs create mode 100644 osu.Game/Screens/Ranking/Types/IResultType.cs create mode 100644 osu.Game/Screens/Ranking/Types/RankingResultType.cs create mode 100644 osu.Game/Screens/Ranking/Types/ScoreResultType.cs diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/TestCaseResults.cs index 6a20a808b6..a954c6c57c 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/TestCaseResults.cs @@ -8,7 +8,9 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; +using osu.Game.Screens.Ranking.Pages; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -23,8 +25,8 @@ namespace osu.Game.Tests.Visual typeof(ScoreInfo), typeof(Results), typeof(ResultsPage), - typeof(ResultsPageScore), - typeof(ResultsPageRanking) + typeof(ScoreResultsPage), + typeof(RankingResultsPage) }; [BackgroundDependencyLoader] @@ -41,7 +43,7 @@ namespace osu.Game.Tests.Visual if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); - Add(new Results(new ScoreInfo + Add(new SoloResults(new ScoreInfo { TotalScore = 2845370, Accuracy = 0.98, diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 19b49b099c..1429675ddd 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -28,7 +28,6 @@ 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; @@ -288,7 +287,7 @@ namespace osu.Game.Screens.Play if (RulesetContainer.Replay == null) scoreManager.Import(score, true); - Push(new Results(score)); + Push(new SoloResults(score)); onCompletionEvent = null; }); diff --git a/osu.Game/Screens/Play/SoloResults.cs b/osu.Game/Screens/Play/SoloResults.cs new file mode 100644 index 0000000000..717efd118e --- /dev/null +++ b/osu.Game/Screens/Play/SoloResults.cs @@ -0,0 +1,24 @@ +// 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.Game.Scoring; +using osu.Game.Screens.Ranking; +using osu.Game.Screens.Ranking.Types; + +namespace osu.Game.Screens.Play +{ + public class SoloResults : Results + { + public SoloResults(ScoreInfo score) + : base(score) + { + } + + protected override IEnumerable CreateResultTypes() => new IResultType[] + { + new ScoreResultType(Score, Beatmap), + new RankingResultType(Score, Beatmap) + }; + } +} diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/Pages/RankingResultsPage.cs similarity index 83% rename from osu.Game/Screens/Ranking/ResultsPageRanking.cs rename to osu.Game/Screens/Ranking/Pages/RankingResultsPage.cs index 3a75daaf60..4c98e476c4 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/Pages/RankingResultsPage.cs @@ -3,18 +3,19 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Scoring; using osu.Game.Screens.Select.Leaderboards; using osuTK; -using osu.Framework.Graphics.Shapes; -using osu.Game.Scoring; -namespace osu.Game.Screens.Ranking +namespace osu.Game.Screens.Ranking.Pages { - public class ResultsPageRanking : ResultsPage + public class RankingResultsPage : ResultsPage { - public ResultsPageRanking(ScoreInfo score, WorkingBeatmap beatmap = null) : base(score, beatmap) + public RankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap = null) + : base(score, beatmap) { } diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ResultsPage.cs similarity index 98% rename from osu.Game/Screens/Ranking/ResultsPage.cs rename to osu.Game/Screens/Ranking/Pages/ResultsPage.cs index 5f68623e54..2e379d0a76 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ResultsPage.cs @@ -12,7 +12,7 @@ using osu.Game.Scoring; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Ranking +namespace osu.Game.Screens.Ranking.Pages { public class ResultsPage : Container { diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs similarity index 98% rename from osu.Game/Screens/Ranking/ResultsPageScore.cs rename to osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 0774a63e98..8f5b21a7cb 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -4,36 +4,39 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; using osu.Game.Screens.Play; using osu.Game.Users; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Extensions; -using osu.Framework.Localisation; -using osu.Game.Online.Leaderboards; -using osu.Game.Scoring; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Screens.Ranking +namespace osu.Game.Screens.Ranking.Pages { - public class ResultsPageScore : ResultsPage + public class ScoreResultsPage : ResultsPage { private Container scoreContainer; private ScoreCounter scoreCounter; - public ResultsPageScore(ScoreInfo score, WorkingBeatmap beatmap) : base(score, beatmap) { } + public ScoreResultsPage(ScoreInfo score, WorkingBeatmap beatmap) + : base(score, beatmap) + { + } private FillFlowContainer statisticsContainer; diff --git a/osu.Game/Screens/Ranking/ResultMode.cs b/osu.Game/Screens/Ranking/ResultMode.cs deleted file mode 100644 index 4742864b83..0000000000 --- a/osu.Game/Screens/Ranking/ResultMode.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Screens.Ranking -{ - public enum ResultMode - { - Summary, - Ranking, - Share - } -} diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index 5df3ff3afb..da0eb3dfcc 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -10,30 +10,21 @@ using osu.Game.Graphics; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Screens.Ranking.Types; namespace osu.Game.Screens.Ranking { - public class ResultModeButton : TabItem + public class ResultModeButton : TabItem { private readonly FontAwesome icon; private Color4 activeColour; private Color4 inactiveColour; private CircularContainer colouredPart; - public ResultModeButton(ResultMode mode) : base(mode) + public ResultModeButton(IResultType mode) + : base(mode) { - switch (mode) - { - case ResultMode.Summary: - icon = FontAwesome.fa_asterisk; - break; - case ResultMode.Ranking: - icon = FontAwesome.fa_list; - break; - case ResultMode.Share: - icon = FontAwesome.fa_camera; - break; - } + icon = mode.Icon; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Ranking/ResultModeTabControl.cs b/osu.Game/Screens/Ranking/ResultModeTabControl.cs index e5c6115085..cc1f7bc6b2 100644 --- a/osu.Game/Screens/Ranking/ResultModeTabControl.cs +++ b/osu.Game/Screens/Ranking/ResultModeTabControl.cs @@ -3,11 +3,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; +using osu.Game.Screens.Ranking.Types; using osuTK; namespace osu.Game.Screens.Ranking { - public class ResultModeTabControl : TabControl + public class ResultModeTabControl : TabControl { public ResultModeTabControl() { @@ -19,9 +20,9 @@ namespace osu.Game.Screens.Ranking TabContainer.Padding = new MarginPadding(5); } - protected override Dropdown CreateDropdown() => null; + protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(ResultMode value) => new ResultModeButton(value) + protected override TabItem CreateTabItem(IResultType value) => new ResultModeButton(value) { Anchor = TabContainer.Anchor, Origin = TabContainer.Origin diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 1ff5fc7bfd..e7340b2c33 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -2,6 +2,7 @@ // 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.Extensions.Color4Extensions; using osu.Framework.Extensions.IEnumerableExtensions; @@ -18,12 +19,12 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Types; namespace osu.Game.Screens.Ranking { - public class Results : OsuScreen + public abstract class Results : OsuScreen { - private readonly ScoreInfo score; private Container circleOuterBackground; private Container circleOuter; private Container circleInner; @@ -34,6 +35,8 @@ namespace osu.Game.Screens.Ranking public override bool AllowBeatmapRulesetChange => false; + protected readonly ScoreInfo Score; + private Container currentPage; private static readonly Vector2 background_blur = new Vector2(20); @@ -44,9 +47,9 @@ namespace osu.Game.Screens.Ranking private const float circle_outer_scale = 0.96f; - public Results(ScoreInfo score) + protected Results(ScoreInfo score) { - this.score = score; + Score = score; } private const float transition_time = 800; @@ -67,7 +70,7 @@ namespace osu.Game.Screens.Ranking backgroundParallax.FadeOut(); modeChangeButtons.FadeOut(); - currentPage.FadeOut(); + currentPage?.FadeOut(); circleOuterBackground .FadeIn(transition_time, Easing.OutQuint) @@ -90,7 +93,7 @@ namespace osu.Game.Screens.Ranking using (BeginDelayedSequence(transition_time * 0.4f, true)) { modeChangeButtons.FadeIn(transition_time, Easing.OutQuint); - currentPage.FadeIn(transition_time, Easing.OutQuint); + currentPage?.FadeIn(transition_time, Easing.OutQuint); } } } @@ -188,7 +191,7 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { - Text = $"{score.MaxCombo}x", + Text = $"{Score.MaxCombo}x", TextSize = 40, RelativePositionAxes = Axes.X, Font = @"Exo2.0-Bold", @@ -209,7 +212,7 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { - Text = $"{score.Accuracy:P2}", + Text = $"{Score.Accuracy:P2}", TextSize = 40, RelativePositionAxes = Axes.X, Font = @"Exo2.0-Bold", @@ -262,30 +265,22 @@ namespace osu.Game.Screens.Ranking }, }; - modeChangeButtons.AddItem(ResultMode.Summary); - modeChangeButtons.AddItem(ResultMode.Ranking); - //modeChangeButtons.AddItem(ResultMode.Share); + foreach (var t in CreateResultTypes()) + modeChangeButtons.AddItem(t); + modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault(); - modeChangeButtons.Current.ValueChanged += mode => + modeChangeButtons.Current.BindValueChanged(m => { currentPage?.FadeOut(); currentPage?.Expire(); - switch (mode) - { - case ResultMode.Summary: - currentPage = new ResultsPageScore(score, Beatmap.Value); - break; - case ResultMode.Ranking: - currentPage = new ResultsPageRanking(score, Beatmap.Value); - break; - } + currentPage = m?.CreatePage(); if (currentPage != null) circleInner.Add(currentPage); - }; - - modeChangeButtons.Current.TriggerChange(); + }, true); } + + protected abstract IEnumerable CreateResultTypes(); } } diff --git a/osu.Game/Screens/Ranking/Types/IResultType.cs b/osu.Game/Screens/Ranking/Types/IResultType.cs new file mode 100644 index 0000000000..df574e99f1 --- /dev/null +++ b/osu.Game/Screens/Ranking/Types/IResultType.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osu.Game.Screens.Ranking.Pages; + +namespace osu.Game.Screens.Ranking.Types +{ + public interface IResultType + { + FontAwesome Icon { get; } + + ResultsPage CreatePage(); + } +} diff --git a/osu.Game/Screens/Ranking/Types/RankingResultType.cs b/osu.Game/Screens/Ranking/Types/RankingResultType.cs new file mode 100644 index 0000000000..a11732d324 --- /dev/null +++ b/osu.Game/Screens/Ranking/Types/RankingResultType.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Pages; + +namespace osu.Game.Screens.Ranking.Types +{ + public class RankingResultType : IResultType + { + private readonly ScoreInfo score; + private readonly WorkingBeatmap beatmap; + + public RankingResultType(ScoreInfo score, WorkingBeatmap beatmap) + { + this.score = score; + this.beatmap = beatmap; + } + + public FontAwesome Icon => FontAwesome.fa_list; + + public ResultsPage CreatePage() => new RankingResultsPage(score, beatmap); + } +} diff --git a/osu.Game/Screens/Ranking/Types/ScoreResultType.cs b/osu.Game/Screens/Ranking/Types/ScoreResultType.cs new file mode 100644 index 0000000000..0841365528 --- /dev/null +++ b/osu.Game/Screens/Ranking/Types/ScoreResultType.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking.Pages; + +namespace osu.Game.Screens.Ranking.Types +{ + public class ScoreResultType : IResultType + { + private readonly ScoreInfo score; + private readonly WorkingBeatmap beatmap; + + public ScoreResultType(ScoreInfo score, WorkingBeatmap beatmap) + { + this.score = score; + this.beatmap = beatmap; + } + + public FontAwesome Icon => FontAwesome.fa_asterisk; + + public ResultsPage CreatePage() => new ScoreResultsPage(score, beatmap); + } +} diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 71b63c8e5b..f65cc0e49d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -28,7 +28,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Edit; using osu.Game.Screens.Menu; -using osu.Game.Screens.Ranking; +using osu.Game.Screens.Play; using osu.Game.Screens.Select.Options; using osu.Game.Skinning; @@ -210,7 +210,7 @@ namespace osu.Game.Screens.Select }); } - BeatmapDetails.Leaderboard.ScoreSelected += s => Push(new Results(s)); + BeatmapDetails.Leaderboard.ScoreSelected += s => Push(new SoloResults(s)); } [BackgroundDependencyLoader(true)] From b9ec179713b1972810055caf5b3b894e1b649964 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 15:45:16 +0900 Subject: [PATCH 246/355] Split out more requests + responses --- osu.Game.Tests/Visual/TestCaseMultiResults.cs | 5 ++- .../API/Requests/CreateRoomScoreRequest.cs | 2 +- .../API/Requests/GetRoomScoresRequest.cs | 20 ++++++++++ .../Requests/Responses/APIRoomScoreInfo.cs | 17 +++++++++ .../{APIRoomScore.cs => APIScoreToken.cs} | 2 +- .../Match/Components/MatchLeaderboard.cs | 38 +++++-------------- .../Ranking/Pages/RoomRankingResultsPage.cs | 5 ++- 7 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetRoomScoresRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs rename osu.Game/Online/API/Requests/Responses/{APIRoomScore.cs => APIScoreToken.cs} (90%) diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMultiResults.cs index 988ba0efdc..deb5d88ad2 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiResults.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiResults.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Match.Components; @@ -101,7 +102,7 @@ namespace osu.Game.Tests.Visual { } - protected override APIRequest FetchScores(Action> scoresCallback) + protected override APIRequest FetchScores(Action> scoresCallback) { var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray(); @@ -111,7 +112,7 @@ namespace osu.Game.Tests.Visual return null; } - private RoomScore createRoomScore(int id) => new RoomScore + private APIRoomScoreInfo createRoomScore(int id) => new APIRoomScoreInfo { User = new User { Id = id, Username = $"User {id}" }, Accuracy = 0.98, diff --git a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs b/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs index 99640f435e..0e99b53ec0 100644 --- a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs +++ b/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs @@ -7,7 +7,7 @@ using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { - public class CreateRoomScoreRequest : APIRequest + public class CreateRoomScoreRequest : APIRequest { private readonly int roomId; private readonly int playlistItemId; diff --git a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs b/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs new file mode 100644 index 0000000000..1699694878 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs @@ -0,0 +1,20 @@ +// 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.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetRoomScoresRequest : APIRequest> + { + private readonly int roomId; + + public GetRoomScoresRequest(int roomId) + { + this.roomId = roomId; + } + + protected override string Target => $@"rooms/{roomId}/leaderboard"; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs new file mode 100644 index 0000000000..2394db3825 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs @@ -0,0 +1,17 @@ +// 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.Scoring; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIRoomScoreInfo : ScoreInfo + { + [JsonProperty("attempts")] + public int TotalAttempts { get; set; } + + [JsonProperty("completed")] + public int CompletedAttempts { get; set; } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIRoomScore.cs b/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs similarity index 90% rename from osu.Game/Online/API/Requests/Responses/APIRoomScore.cs rename to osu.Game/Online/API/Requests/Responses/APIScoreToken.cs index 9bf67836f6..6a0ecd37c7 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRoomScore.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs @@ -5,7 +5,7 @@ using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses { - public class APIRoomScore + public class APIScoreToken { [JsonProperty("id")] public int ID { get; set; } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index d6c7c28840..f61a1dde43 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -3,19 +3,20 @@ using System; using System.Collections.Generic; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; namespace osu.Game.Screens.Multi.Match.Components { - public class MatchLeaderboard : Leaderboard + public class MatchLeaderboard : Leaderboard { - public Action> ScoresLoaded; + public Action> ScoresLoaded; private readonly Room room; @@ -34,7 +35,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, true); } - protected override APIRequest FetchScores(Action> scoresCallback) + protected override APIRequest FetchScores(Action> scoresCallback) { if (room.RoomID == null) return null; @@ -50,24 +51,12 @@ namespace osu.Game.Screens.Multi.Match.Components return req; } - protected override LeaderboardScore CreateDrawableScore(RoomScore model, int index) => new MatchLeaderboardScore(model, index); - - private class GetRoomScoresRequest : APIRequest> - { - private readonly int roomId; - - public GetRoomScoresRequest(int roomId) - { - this.roomId = roomId; - } - - protected override string Target => $@"rooms/{roomId}/leaderboard"; - } + protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) => new MatchLeaderboardScore(model, index); } public class MatchLeaderboardScore : LeaderboardScore { - public MatchLeaderboardScore(RoomScore score, int rank) + public MatchLeaderboardScore(APIRoomScoreInfo score, int rank) : base(score, rank) { } @@ -81,8 +70,8 @@ namespace osu.Game.Screens.Multi.Match.Components protected override IEnumerable GetStatistics(ScoreInfo model) => new[] { new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), - new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((RoomScore)model).TotalAttempts.ToString()), - new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((RoomScore)model).CompletedAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedAttempts.ToString()), }; } @@ -90,13 +79,4 @@ namespace osu.Game.Screens.Multi.Match.Components { Overall } - - public class RoomScore : ScoreInfo - { - [JsonProperty("attempts")] - public int TotalAttempts { get; set; } - - [JsonProperty("completed")] - public int CompletedAttempts { get; set; } - } } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs index 6c46973ca7..e277a83bb4 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Match.Components; @@ -73,13 +74,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages leaderboard.ScoresLoaded = scoresLoaded; } - private void scoresLoaded(IEnumerable scores) + private void scoresLoaded(IEnumerable scores) { Action gray = s => s.Colour = colours.Gray8; rankText.AddText("You are placed ", gray); - int index = scores.IndexOf(new RoomScore { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); + int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); rankText.AddText($"#{index + 1} ", s => { From baed0ef3baa1f5df34d7af86cf449f41289f1c9a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 15:46:04 +0900 Subject: [PATCH 247/355] Rename variable --- osu.Game.Tests/Visual/TestCaseMultiResults.cs | 2 +- osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs | 2 +- osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMultiResults.cs index deb5d88ad2..607a8cff3e 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiResults.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiResults.cs @@ -118,7 +118,7 @@ namespace osu.Game.Tests.Visual Accuracy = 0.98, TotalScore = 987654, TotalAttempts = 13, - CompletedAttempts = 5 + CompletedBeatmaps = 5 }; } } diff --git a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs index 2394db3825..c6ef919e54 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs @@ -12,6 +12,6 @@ namespace osu.Game.Online.API.Requests.Responses public int TotalAttempts { get; set; } [JsonProperty("completed")] - public int CompletedAttempts { get; set; } + public int CompletedBeatmaps { get; set; } } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index f61a1dde43..4d574ff9ef 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()), - new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedBeatmaps.ToString()), }; } From e404a0bc201d4a6e93b8ae47566998e78f5744f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 15:51:00 +0900 Subject: [PATCH 248/355] Clean-ups and renames --- osu.Game/Screens/Play/SoloResults.cs | 6 +++--- osu.Game/Screens/Ranking/{Types => }/IResultType.cs | 7 ++++--- osu.Game/Screens/Ranking/ResultModeButton.cs | 5 ++--- osu.Game/Screens/Ranking/ResultModeTabControl.cs | 7 +++---- osu.Game/Screens/Ranking/Results.cs | 3 +-- osu.Game/Screens/Ranking/{Pages => }/ResultsPage.cs | 6 +++--- ...{RankingResultType.cs => BeatmapLeaderboardPageInfo.cs} | 6 ++++-- .../Types/{ScoreResultType.cs => ScoreOverviewPageInfo.cs} | 6 ++++-- 8 files changed, 24 insertions(+), 22 deletions(-) rename osu.Game/Screens/Ranking/{Types => }/IResultType.cs (70%) rename osu.Game/Screens/Ranking/{Pages => }/ResultsPage.cs (94%) rename osu.Game/Screens/Ranking/Types/{RankingResultType.cs => BeatmapLeaderboardPageInfo.cs} (76%) rename osu.Game/Screens/Ranking/Types/{ScoreResultType.cs => ScoreOverviewPageInfo.cs} (77%) diff --git a/osu.Game/Screens/Play/SoloResults.cs b/osu.Game/Screens/Play/SoloResults.cs index 717efd118e..2828c758e0 100644 --- a/osu.Game/Screens/Play/SoloResults.cs +++ b/osu.Game/Screens/Play/SoloResults.cs @@ -15,10 +15,10 @@ namespace osu.Game.Screens.Play { } - protected override IEnumerable CreateResultTypes() => new IResultType[] + protected override IEnumerable CreateResultTypes() => new IResultPageInfo[] { - new ScoreResultType(Score, Beatmap), - new RankingResultType(Score, Beatmap) + new ScoreOverviewPageInfo(Score, Beatmap), + new BeatmapLeaderboardPageInfo(Score, Beatmap) }; } } diff --git a/osu.Game/Screens/Ranking/Types/IResultType.cs b/osu.Game/Screens/Ranking/IResultType.cs similarity index 70% rename from osu.Game/Screens/Ranking/Types/IResultType.cs rename to osu.Game/Screens/Ranking/IResultType.cs index df574e99f1..5c6d08d883 100644 --- a/osu.Game/Screens/Ranking/Types/IResultType.cs +++ b/osu.Game/Screens/Ranking/IResultType.cs @@ -2,14 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; -using osu.Game.Screens.Ranking.Pages; -namespace osu.Game.Screens.Ranking.Types +namespace osu.Game.Screens.Ranking { - public interface IResultType + public interface IResultPageInfo { FontAwesome Icon { get; } + string Name { get; } + ResultsPage CreatePage(); } } diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index da0eb3dfcc..34a93236bd 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -10,18 +10,17 @@ using osu.Game.Graphics; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Screens.Ranking.Types; namespace osu.Game.Screens.Ranking { - public class ResultModeButton : TabItem + public class ResultModeButton : TabItem { private readonly FontAwesome icon; private Color4 activeColour; private Color4 inactiveColour; private CircularContainer colouredPart; - public ResultModeButton(IResultType mode) + public ResultModeButton(IResultPageInfo mode) : base(mode) { icon = mode.Icon; diff --git a/osu.Game/Screens/Ranking/ResultModeTabControl.cs b/osu.Game/Screens/Ranking/ResultModeTabControl.cs index cc1f7bc6b2..e87749d8dd 100644 --- a/osu.Game/Screens/Ranking/ResultModeTabControl.cs +++ b/osu.Game/Screens/Ranking/ResultModeTabControl.cs @@ -3,12 +3,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; -using osu.Game.Screens.Ranking.Types; using osuTK; namespace osu.Game.Screens.Ranking { - public class ResultModeTabControl : TabControl + public class ResultModeTabControl : TabControl { public ResultModeTabControl() { @@ -20,9 +19,9 @@ namespace osu.Game.Screens.Ranking TabContainer.Padding = new MarginPadding(5); } - protected override Dropdown CreateDropdown() => null; + protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(IResultType value) => new ResultModeButton(value) + protected override TabItem CreateTabItem(IResultPageInfo value) => new ResultModeButton(value) { Anchor = TabContainer.Anchor, Origin = TabContainer.Origin diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index e7340b2c33..86067d8cc5 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -19,7 +19,6 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; -using osu.Game.Screens.Ranking.Types; namespace osu.Game.Screens.Ranking { @@ -281,6 +280,6 @@ namespace osu.Game.Screens.Ranking }, true); } - protected abstract IEnumerable CreateResultTypes(); + protected abstract IEnumerable CreateResultTypes(); } } diff --git a/osu.Game/Screens/Ranking/Pages/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs similarity index 94% rename from osu.Game/Screens/Ranking/Pages/ResultsPage.cs rename to osu.Game/Screens/Ranking/ResultsPage.cs index 2e379d0a76..08c6155557 100644 --- a/osu.Game/Screens/Ranking/Pages/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -12,9 +12,9 @@ using osu.Game.Scoring; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Ranking.Pages +namespace osu.Game.Screens.Ranking { - public class ResultsPage : Container + public abstract class ResultsPage : Container { protected readonly ScoreInfo Score; protected readonly WorkingBeatmap Beatmap; @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Ranking.Pages protected override Container Content => content; - public ResultsPage(ScoreInfo score, WorkingBeatmap beatmap) + protected ResultsPage(ScoreInfo score, WorkingBeatmap beatmap) { Score = score; Beatmap = beatmap; diff --git a/osu.Game/Screens/Ranking/Types/RankingResultType.cs b/osu.Game/Screens/Ranking/Types/BeatmapLeaderboardPageInfo.cs similarity index 76% rename from osu.Game/Screens/Ranking/Types/RankingResultType.cs rename to osu.Game/Screens/Ranking/Types/BeatmapLeaderboardPageInfo.cs index a11732d324..2b192d4bcd 100644 --- a/osu.Game/Screens/Ranking/Types/RankingResultType.cs +++ b/osu.Game/Screens/Ranking/Types/BeatmapLeaderboardPageInfo.cs @@ -8,12 +8,12 @@ using osu.Game.Screens.Ranking.Pages; namespace osu.Game.Screens.Ranking.Types { - public class RankingResultType : IResultType + public class BeatmapLeaderboardPageInfo : IResultPageInfo { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; - public RankingResultType(ScoreInfo score, WorkingBeatmap beatmap) + public BeatmapLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap) { this.score = score; this.beatmap = beatmap; @@ -21,6 +21,8 @@ namespace osu.Game.Screens.Ranking.Types public FontAwesome Icon => FontAwesome.fa_list; + public string Name => @"Beatmap Leaderboard"; + public ResultsPage CreatePage() => new RankingResultsPage(score, beatmap); } } diff --git a/osu.Game/Screens/Ranking/Types/ScoreResultType.cs b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs similarity index 77% rename from osu.Game/Screens/Ranking/Types/ScoreResultType.cs rename to osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs index 0841365528..13930fe689 100644 --- a/osu.Game/Screens/Ranking/Types/ScoreResultType.cs +++ b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs @@ -8,18 +8,20 @@ using osu.Game.Screens.Ranking.Pages; namespace osu.Game.Screens.Ranking.Types { - public class ScoreResultType : IResultType + public class ScoreOverviewPageInfo : IResultPageInfo { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; - public ScoreResultType(ScoreInfo score, WorkingBeatmap beatmap) + public ScoreOverviewPageInfo(ScoreInfo score, WorkingBeatmap beatmap) { this.score = score; this.beatmap = beatmap; } public FontAwesome Icon => FontAwesome.fa_asterisk; + + public string Name => "Overview"; public ResultsPage CreatePage() => new ScoreResultsPage(score, beatmap); } From e7508cbd5efe7f1a74d6e1fbbccc33725697af04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 15:55:10 +0900 Subject: [PATCH 249/355] Fix CI issues --- .../Ranking/{IResultType.cs => IResultPageInfo.cs} | 0 .../Screens/Ranking/Types/ScoreOverviewPageInfo.cs | 12 +++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) rename osu.Game/Screens/Ranking/{IResultType.cs => IResultPageInfo.cs} (100%) diff --git a/osu.Game/Screens/Ranking/IResultType.cs b/osu.Game/Screens/Ranking/IResultPageInfo.cs similarity index 100% rename from osu.Game/Screens/Ranking/IResultType.cs rename to osu.Game/Screens/Ranking/IResultPageInfo.cs diff --git a/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs index 13930fe689..03998d2840 100644 --- a/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs +++ b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs @@ -10,6 +10,9 @@ namespace osu.Game.Screens.Ranking.Types { public class ScoreOverviewPageInfo : IResultPageInfo { + public FontAwesome Icon => FontAwesome.fa_asterisk; + + public string Name => "Overview"; private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; @@ -19,10 +22,9 @@ namespace osu.Game.Screens.Ranking.Types this.beatmap = beatmap; } - public FontAwesome Icon => FontAwesome.fa_asterisk; - - public string Name => "Overview"; - - public ResultsPage CreatePage() => new ScoreResultsPage(score, beatmap); + public ResultsPage CreatePage() + { + return new ScoreResultsPage(score, beatmap); + } } } From a35d9178f05bb58ae1aac22e5d6849da55894d68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 16:20:29 +0900 Subject: [PATCH 250/355] Quick rename --- osu.Game/Screens/Play/SoloResults.cs | 2 +- osu.Game/Screens/Ranking/Results.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/SoloResults.cs b/osu.Game/Screens/Play/SoloResults.cs index 2828c758e0..5e318e95d1 100644 --- a/osu.Game/Screens/Play/SoloResults.cs +++ b/osu.Game/Screens/Play/SoloResults.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Play { } - protected override IEnumerable CreateResultTypes() => new IResultPageInfo[] + protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { new ScoreOverviewPageInfo(Score, Beatmap), new BeatmapLeaderboardPageInfo(Score, Beatmap) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 86067d8cc5..bf9e3bcd27 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -264,7 +264,7 @@ namespace osu.Game.Screens.Ranking }, }; - foreach (var t in CreateResultTypes()) + foreach (var t in CreateResultPages()) modeChangeButtons.AddItem(t); modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault(); @@ -280,6 +280,6 @@ namespace osu.Game.Screens.Ranking }, true); } - protected abstract IEnumerable CreateResultTypes(); + protected abstract IEnumerable CreateResultPages(); } } From bb08bf10a08d86bc214dc333988bd77a46a142d1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 16:26:27 +0900 Subject: [PATCH 251/355] Fix post-merge issues --- osu.Game.Tests/Visual/TestCaseMultiResults.cs | 16 ++++-------- .../Screens/Multi/Ranking/MultiResults.cs | 8 +++--- .../Ranking/Pages/RoomRankingResultsPage.cs | 2 +- ...sultType.cs => RoomLeaderboardPageInfo.cs} | 9 ++++--- osu.Game/Screens/Play/Player.cs | 5 +++- .../Ranking/{Pages => }/ResultsPage.cs | 2 +- osu.Game/Screens/Ranking/Types/IResultType.cs | 15 ----------- .../Ranking/Types/RankingResultType.cs | 26 ------------------- .../Screens/Ranking/Types/ScoreResultType.cs | 26 ------------------- 9 files changed, 20 insertions(+), 89 deletions(-) rename osu.Game/Screens/Multi/Ranking/Types/{RoomRankingResultType.cs => RoomLeaderboardPageInfo.cs} (76%) rename osu.Game/Screens/Ranking/{Pages => }/ResultsPage.cs (98%) delete mode 100644 osu.Game/Screens/Ranking/Types/IResultType.cs delete mode 100644 osu.Game/Screens/Ranking/Types/RankingResultType.cs delete mode 100644 osu.Game/Screens/Ranking/Types/ScoreResultType.cs diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMultiResults.cs index 607a8cff3e..38027e0bc3 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiResults.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiResults.cs @@ -14,8 +14,7 @@ using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Multi.Ranking.Pages; using osu.Game.Screens.Multi.Ranking.Types; -using osu.Game.Screens.Ranking.Pages; -using osu.Game.Screens.Ranking.Types; +using osu.Game.Screens.Ranking; using osu.Game.Users; namespace osu.Game.Tests.Visual @@ -25,7 +24,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(MultiResults), - typeof(RoomRankingResultType), + typeof(RoomLeaderboardPageInfo), typeof(RoomRankingResultsPage) }; @@ -60,21 +59,16 @@ namespace osu.Game.Tests.Visual this.room = room; } - protected override IEnumerable CreateResultTypes() => new IResultType[] - { - new ScoreResultType(Score, Beatmap), - new RankingResultType(Score, Beatmap), - new TestRoomRankingResultType(Score, Beatmap, room), - }; + protected override IEnumerable CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap, room) }; } - private class TestRoomRankingResultType : RoomRankingResultType + private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; private readonly Room room; - public TestRoomRankingResultType(ScoreInfo score, WorkingBeatmap beatmap, Room room) + public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room) : base(score, beatmap, room) { this.score = score; diff --git a/osu.Game/Screens/Multi/Ranking/MultiResults.cs b/osu.Game/Screens/Multi/Ranking/MultiResults.cs index 4358943057..0fffe250bf 100644 --- a/osu.Game/Screens/Multi/Ranking/MultiResults.cs +++ b/osu.Game/Screens/Multi/Ranking/MultiResults.cs @@ -20,11 +20,11 @@ namespace osu.Game.Screens.Multi.Ranking this.room = room; } - protected override IEnumerable CreateResultTypes() => new IResultType[] + protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { - new ScoreResultType(Score, Beatmap), - new RankingResultType(Score, Beatmap), - new RoomRankingResultType(Score, Beatmap, room), + new ScoreOverviewPageInfo(Score, Beatmap), + new BeatmapLeaderboardPageInfo(Score, Beatmap), + new RoomLeaderboardPageInfo(Score, Beatmap, room), }; } } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs index e277a83bb4..a3836ed82a 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs @@ -16,7 +16,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Match.Components; -using osu.Game.Screens.Ranking.Pages; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Multi.Ranking.Pages { diff --git a/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs similarity index 76% rename from osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs rename to osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs index 963a9ff1cf..07429b0b89 100644 --- a/osu.Game/Screens/Multi/Ranking/Types/RoomRankingResultType.cs +++ b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs @@ -6,18 +6,17 @@ using osu.Game.Graphics; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking.Pages; -using osu.Game.Screens.Ranking.Pages; -using osu.Game.Screens.Ranking.Types; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Multi.Ranking.Types { - public class RoomRankingResultType : IResultType + public class RoomLeaderboardPageInfo : IResultPageInfo { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; private readonly Room room; - public RoomRankingResultType(ScoreInfo score, WorkingBeatmap beatmap, Room room) + public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room) { this.score = score; this.beatmap = beatmap; @@ -26,6 +25,8 @@ namespace osu.Game.Screens.Multi.Ranking.Types public FontAwesome Icon => FontAwesome.fa_list; + public string Name => "Room Leaderboard"; + public virtual ResultsPage CreatePage() => new RoomRankingResultsPage(score, beatmap, room); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 1429675ddd..f2390318b0 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -28,6 +28,7 @@ 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; @@ -287,7 +288,7 @@ namespace osu.Game.Screens.Play if (RulesetContainer.Replay == null) scoreManager.Import(score, true); - Push(new SoloResults(score)); + Push(CreateResults(score)); onCompletionEvent = null; }); @@ -431,5 +432,7 @@ namespace osu.Game.Screens.Play if (storyboardVisible && beatmap.Storyboard.ReplacesBackground) Background?.FadeTo(0, BACKGROUND_FADE_DURATION, Easing.OutQuint); } + + protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score); } } diff --git a/osu.Game/Screens/Ranking/Pages/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs similarity index 98% rename from osu.Game/Screens/Ranking/Pages/ResultsPage.cs rename to osu.Game/Screens/Ranking/ResultsPage.cs index 3f077f5759..08c6155557 100644 --- a/osu.Game/Screens/Ranking/Pages/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -12,7 +12,7 @@ using osu.Game.Scoring; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Ranking.Pages +namespace osu.Game.Screens.Ranking { public abstract class ResultsPage : Container { diff --git a/osu.Game/Screens/Ranking/Types/IResultType.cs b/osu.Game/Screens/Ranking/Types/IResultType.cs deleted file mode 100644 index df574e99f1..0000000000 --- a/osu.Game/Screens/Ranking/Types/IResultType.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Graphics; -using osu.Game.Screens.Ranking.Pages; - -namespace osu.Game.Screens.Ranking.Types -{ - public interface IResultType - { - FontAwesome Icon { get; } - - ResultsPage CreatePage(); - } -} diff --git a/osu.Game/Screens/Ranking/Types/RankingResultType.cs b/osu.Game/Screens/Ranking/Types/RankingResultType.cs deleted file mode 100644 index a11732d324..0000000000 --- a/osu.Game/Screens/Ranking/Types/RankingResultType.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Scoring; -using osu.Game.Screens.Ranking.Pages; - -namespace osu.Game.Screens.Ranking.Types -{ - public class RankingResultType : IResultType - { - private readonly ScoreInfo score; - private readonly WorkingBeatmap beatmap; - - public RankingResultType(ScoreInfo score, WorkingBeatmap beatmap) - { - this.score = score; - this.beatmap = beatmap; - } - - public FontAwesome Icon => FontAwesome.fa_list; - - public ResultsPage CreatePage() => new RankingResultsPage(score, beatmap); - } -} diff --git a/osu.Game/Screens/Ranking/Types/ScoreResultType.cs b/osu.Game/Screens/Ranking/Types/ScoreResultType.cs deleted file mode 100644 index 0841365528..0000000000 --- a/osu.Game/Screens/Ranking/Types/ScoreResultType.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Scoring; -using osu.Game.Screens.Ranking.Pages; - -namespace osu.Game.Screens.Ranking.Types -{ - public class ScoreResultType : IResultType - { - private readonly ScoreInfo score; - private readonly WorkingBeatmap beatmap; - - public ScoreResultType(ScoreInfo score, WorkingBeatmap beatmap) - { - this.score = score; - this.beatmap = beatmap; - } - - public FontAwesome Icon => FontAwesome.fa_asterisk; - - public ResultsPage CreatePage() => new ScoreResultsPage(score, beatmap); - } -} From 005c6ff40c6212da2c4a279cb976a8f3edbcb747 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 22 Dec 2018 16:30:06 +0900 Subject: [PATCH 252/355] Add tooltip text to results screen pages --- osu.Game/Screens/Ranking/ResultModeButton.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index 34a93236bd..f6a886418c 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osuTK; @@ -13,7 +14,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Ranking { - public class ResultModeButton : TabItem + public class ResultModeButton : TabItem, IHasTooltip { private readonly FontAwesome icon; private Color4 activeColour; @@ -24,6 +25,7 @@ namespace osu.Game.Screens.Ranking : base(mode) { icon = mode.Icon; + TooltipText = mode.Name; } [BackgroundDependencyLoader] @@ -85,5 +87,7 @@ namespace osu.Game.Screens.Ranking protected override void OnActivated() => colouredPart.FadeColour(activeColour, 200, Easing.OutQuint); protected override void OnDeactivated() => colouredPart.FadeColour(inactiveColour, 200, Easing.OutQuint); + + public string TooltipText { get; private set; } } } From 0757beb3b87db23fc58829cef951ec1b6e55792f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 17:54:04 +0900 Subject: [PATCH 253/355] Test for null before loading --- osu.Game/Overlays/AccountCreation/ScreenWarning.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index b6fffde621..082eb8a51f 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -42,6 +42,10 @@ namespace osu.Game.Overlays.AccountCreation private void load(OsuColour colours, APIAccess api, OsuGame game, TextureStore textures) { this.api = api; + + if (string.IsNullOrEmpty(api.ProvidedUsername)) + return; + Children = new Drawable[] { new Sprite From 30dbc36fce3284f292701ee0f1bc4264abcf9cfc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 17:54:19 +0900 Subject: [PATCH 254/355] Don't clear username on logout --- osu.Game/Online/API/APIAccess.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index a3719d624c..8038c1fc1f 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -161,7 +161,7 @@ namespace osu.Game.Online.API //hard bail if we can't get a valid access token. if (authentication.RequestAccessToken() == null) { - Logout(false); + Logout(); continue; } @@ -293,7 +293,7 @@ namespace osu.Game.Online.API switch (statusCode) { case HttpStatusCode.Unauthorized: - Logout(false); + Logout(); return true; case HttpStatusCode.RequestTimeout: failureCount++; @@ -342,10 +342,9 @@ namespace osu.Game.Online.API } } - public void Logout(bool clearUsername = true) + public void Logout() { flushQueue(); - if (clearUsername) ProvidedUsername = null; password = null; authentication.Clear(); LocalUser.Value = createGuestUser(); From 40db23ff4c6d3583b01ad158bcd30f0ab1d46750 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 22 Dec 2018 19:30:52 +0900 Subject: [PATCH 255/355] Disable avatar clicks in chat tabs --- osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index e04d7891f8..804ddeabb4 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -52,6 +52,7 @@ namespace osu.Game.Overlays.Chat.Tabs Child = new DelayedLoadWrapper(new Avatar(value.Users.First()) { RelativeSizeAxes = Axes.Both, + OpenOnClick = { Value = false }, OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), }) { From 8020ac26fbcb1b8a80fce4b0392a9ec0bae8f19c Mon Sep 17 00:00:00 2001 From: VINXIS Date: Sun, 23 Dec 2018 22:14:28 -0700 Subject: [PATCH 256/355] MBMasher's FL change --- .../Difficulty/OsuPerformanceCalculator.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 5e66d43c98..17b9df5cc6 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -123,8 +123,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(h => h is OsuModFlashlight)) { - // Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps. - aimValue *= 1.45f * lengthBonus; + // Apply object-based bonus for flashlight. + aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) + + (numTotalHits > 200 ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + + (numTotalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) : 0.0f); } // Scale the aim value with accuracy _slightly_ From 227c63dd1c6fa6ae85715ab32a50381137173b9f Mon Sep 17 00:00:00 2001 From: VINXIS Date: Sun, 23 Dec 2018 22:23:43 -0700 Subject: [PATCH 257/355] numtotalhits -> totalHits --- osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 17b9df5cc6..16f0af9875 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -125,8 +125,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty { // Apply object-based bonus for flashlight. aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) + - (numTotalHits > 200 ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + - (numTotalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) : 0.0f); + (totalHits > 200 ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + + (totalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) : 0.0f); } // Scale the aim value with accuracy _slightly_ From e0e75c733960adaac76dbcc27a570f99bafb7098 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 11:24:46 +0900 Subject: [PATCH 258/355] Fix incorrect room status --- .../Multi/Lounge/Components/DrawableRoom.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index d6bc0018e4..d62b628389 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -211,14 +211,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, }; - bindings.Status.ValueChanged += s => - { - status.Text = s.Message; - - foreach (Drawable d in new Drawable[] { selectionBox, sideStrip, status }) - d.FadeColour(s.GetAppropriateColour(colours), transition_duration); - }; - background.Beatmap.BindTo(bindings.CurrentBeatmap); modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap); @@ -228,6 +220,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components bindings.Name.BindValueChanged(n => name.Text = n, true); bindings.EndDate.BindValueChanged(d => endDate.Date = d, true); + bindings.Status.BindValueChanged(s => + { + status.Text = s.Message; + + foreach (Drawable d in new Drawable[] { selectionBox, sideStrip, status }) + d.FadeColour(s.GetAppropriateColour(colours), transition_duration); + }, true); } protected override void LoadComplete() From f79aa07d027cb2d2c2a71ef5c1917ecc8560f17d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 11:31:36 +0900 Subject: [PATCH 259/355] Fix enddate not being bound to --- osu.Game/Screens/Multi/RoomBindings.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/RoomBindings.cs b/osu.Game/Screens/Multi/RoomBindings.cs index b5854bf957..e84fa9c261 100644 --- a/osu.Game/Screens/Multi/RoomBindings.cs +++ b/osu.Game/Screens/Multi/RoomBindings.cs @@ -44,8 +44,9 @@ namespace osu.Game.Screens.Multi Status.UnbindFrom(room.Status); Type.UnbindFrom(room.Type); Playlist.UnbindFrom(room.Playlist); - MaxParticipants.UnbindFrom(room.MaxParticipants); Participants.UnbindFrom(room.Participants); + MaxParticipants.UnbindFrom(room.MaxParticipants); + EndDate.UnbindFrom(room.EndDate); Availability.UnbindFrom(room.Availability); Duration.UnbindFrom(room.Duration); } @@ -59,8 +60,9 @@ namespace osu.Game.Screens.Multi Status.BindTo(room.Status); Type.BindTo(room.Type); Playlist.BindTo(room.Playlist); - MaxParticipants.BindTo(room.MaxParticipants); Participants.BindTo(room.Participants); + MaxParticipants.BindTo(room.MaxParticipants); + EndDate.BindTo(room.EndDate); Availability.BindTo(room.Availability); Duration.BindTo(room.Duration); } From 6712a687972c2fcc347846e5f021a3187342f797 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 11:45:50 +0900 Subject: [PATCH 260/355] Create IRoomManager interface, add test for RoomsContainer --- .../Visual/TestCaseLoungeRoomsContainer.cs | 86 +++++++++++++++++++ osu.Game/Screens/Multi/IRoomManager.cs | 46 ++++++++++ .../Multi/Lounge/Components/RoomsContainer.cs | 4 +- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 2 +- .../Match/Components/RoomSettingsOverlay.cs | 2 +- osu.Game/Screens/Multi/Match/MatchScreen.cs | 2 +- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- osu.Game/Screens/Multi/RoomManager.cs | 4 +- 8 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs create mode 100644 osu.Game/Screens/Multi/IRoomManager.cs diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs new file mode 100644 index 0000000000..c6279767a7 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -0,0 +1,86 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Lounge.Components; +using osu.Game.Users; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseLoungeRoomsContainer : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RoomsContainer), + typeof(DrawableRoom) + }; + + [Cached(Type = typeof(IRoomManager))] + private TestRoomManager roomManager = new TestRoomManager(); + + public TestCaseLoungeRoomsContainer() + { + RoomsContainer rooms; + + Child = rooms = new RoomsContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.5f, + JoinRequested = joinRequested + }; + + int roomId = 0; + + AddStep("Add room", () => roomManager.Rooms.Add(new Room + { + Name = { Value = $"Room {++roomId}"}, + Host = { Value = new User { Username = "Host" } }, + EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) } + })); + + AddStep("Remove selected", () => + { + if (rooms.SelectedRoom.Value != null) + roomManager.Rooms.Remove(rooms.SelectedRoom.Value); + }); + } + + private void joinRequested(Room room) => room.Status.Value = new JoinedRoomStatus(); + + private class TestRoomManager : IRoomManager + { + public event Action OpenRequested; + + public readonly BindableCollection Rooms = new BindableCollection(); + IBindableCollection IRoomManager.Rooms => Rooms; + + public void CreateRoom(Room room) => Rooms.Add(room); + + public void JoinRoom(Room room) => OpenRequested?.Invoke(room); + + public void PartRoom() + { + } + + public void Filter(FilterCriteria criteria) + { + } + } + + private class JoinedRoomStatus : RoomStatus + { + public override string Message => "Joined"; + + public override Color4 GetAppropriateColour(OsuColour colours) => colours.Yellow; + } + } +} diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs new file mode 100644 index 0000000000..f09f360ea2 --- /dev/null +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Configuration; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Lounge.Components; + +namespace osu.Game.Screens.Multi +{ + public interface IRoomManager + { + /// + /// Invoked when this requests a to be opened. + /// + event Action OpenRequested; + + /// + /// All the active s. + /// + IBindableCollection Rooms { get; } + + /// + /// Creates a new . + /// + /// The to create. + void CreateRoom(Room room); + + /// + /// Joins a . + /// + /// The to join. must be populated. + void JoinRoom(Room room); + + /// + /// Parts the currently-joined . + /// + void PartRoom(); + + /// + /// Queries for s matching a new . + /// + /// The to match. + void Filter(FilterCriteria criteria); + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index b17ddca21d..6fc544ec80 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly FillFlowContainer roomFlow; [Resolved] - private RoomManager manager { get; set; } + private IRoomManager roomManager { get; set; } public RoomsContainer() { @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components [BackgroundDependencyLoader] private void load() { - rooms.BindTo(manager.Rooms); + rooms.BindTo(roomManager.Rooms); rooms.ItemsAdded += addRooms; rooms.ItemsRemoved += removeRooms; diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 8be7afad8b..82d593033f 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Multi.Lounge private readonly Action pushGameplayScreen; [Resolved(CanBeNull = true)] - private RoomManager roomManager { get; set; } + private IRoomManager roomManager { get; set; } public override string Title => "Lounge"; diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index db29722025..797894e93c 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Multi.Match.Components private readonly Room room; [Resolved(CanBeNull = true)] - private RoomManager manager { get; set; } + private IRoomManager manager { get; set; } public RoomSettingsOverlay(Room room) { diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 927b786ab5..dbbdbb8c54 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Multi.Match private OsuGame game { get; set; } [Resolved(CanBeNull = true)] - private RoomManager manager { get; set; } + private IRoomManager manager { get; set; } public MatchScreen(Room room, Action pushGameplayScreen) { diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 116d4137d5..7a8f9f3948 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Multi private OsuScreen currentScreen; - [Cached] + [Cached(Type = typeof(IRoomManager))] private RoomManager roomManager; public Multiplayer() diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 17c3229b1a..4bd9307bfb 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -17,12 +17,12 @@ using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Screens.Multi { - public class RoomManager : PollingComponent + public class RoomManager : PollingComponent, IRoomManager { public event Action OpenRequested; - public IBindableCollection Rooms => rooms; private readonly BindableCollection rooms = new BindableCollection(); + public IBindableCollection Rooms => rooms; private Room currentRoom; From 626ec85ae833705b6b63445b53f461247b6e3622 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 11:58:28 +0900 Subject: [PATCH 261/355] Remove IHasFilterableChildren from class --- .../Screens/Multi/Lounge/Components/RoomsContainer.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 6fc544ec80..8f4a88d406 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Screens.Multi.Lounge.Components { - public class RoomsContainer : CompositeDrawable, IHasFilterableChildren + public class RoomsContainer : CompositeDrawable { public Action JoinRequested; @@ -114,11 +114,5 @@ namespace osu.Game.Screens.Multi.Lounge.Components selectedRoom.Value = room; } - - public IEnumerable FilterTerms => Enumerable.Empty(); - - public IEnumerable FilterableChildren => InternalChildren.OfType(); - - public bool MatchingFilter { set { } } } } From 23d21a45e5dae455c2c5be8dc3b2e0d49e9d740a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 11:59:08 +0900 Subject: [PATCH 262/355] More automated tests --- .../Visual/TestCaseLoungeRoomsContainer.cs | 39 ++++++++++++------- .../Multi/Lounge/Components/RoomsContainer.cs | 1 + 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index c6279767a7..916468ae2f 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -28,9 +29,9 @@ namespace osu.Game.Tests.Visual public TestCaseLoungeRoomsContainer() { - RoomsContainer rooms; + RoomsContainer container; - Child = rooms = new RoomsContainer + Child = container = new RoomsContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -38,20 +39,32 @@ namespace osu.Game.Tests.Visual JoinRequested = joinRequested }; - int roomId = 0; + AddStep("clear rooms", () => roomManager.Rooms.Clear()); - AddStep("Add room", () => roomManager.Rooms.Add(new Room + AddStep("add rooms", () => { - Name = { Value = $"Room {++roomId}"}, - Host = { Value = new User { Username = "Host" } }, - EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) } - })); - - AddStep("Remove selected", () => - { - if (rooms.SelectedRoom.Value != null) - roomManager.Rooms.Remove(rooms.SelectedRoom.Value); + for (int i = 0; i < 3; i++) + { + roomManager.Rooms.Add(new Room + { + RoomID = { Value = i }, + Name = { Value = $"Room {i}" }, + Host = { Value = new User { Username = "Host" } }, + EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) } + }); + } }); + + AddAssert("has 2 rooms", () => container.Rooms.Count == 3); + AddStep("remove first room", () => roomManager.Rooms.Remove(roomManager.Rooms.FirstOrDefault())); + AddAssert("has 2 rooms", () => container.Rooms.Count == 2); + AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0)); + + AddStep("select first room", () => container.Rooms.First().Action?.Invoke()); + AddAssert("first room selected", () => container.SelectedRoom.Value == roomManager.Rooms.First()); + + AddStep("join first room", () => container.Rooms.First().Action?.Invoke()); + AddAssert("first room joined", () => roomManager.Rooms.First().Status.Value is JoinedRoomStatus); } private void joinRequested(Room room) => room.Status.Value = new JoinedRoomStatus(); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 8f4a88d406..33b71d1203 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -25,6 +25,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly IBindableCollection rooms = new BindableCollection(); private readonly FillFlowContainer roomFlow; + public IReadOnlyList Rooms => roomFlow; [Resolved] private IRoomManager roomManager { get; set; } From 91b83cd4b8fb0de51685756c708fa23ef83070c9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 13:57:25 +0900 Subject: [PATCH 263/355] Fix leaderboard being queried on room creation --- osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 4d574ff9ef..dd5a73817f 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -28,8 +28,11 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - room.RoomID.BindValueChanged(_ => + room.RoomID.BindValueChanged(id => { + if (id == null) + return; + Scores = null; UpdateScores(); }, true); From d4f5a8507c5dd4763161a0c9e83f8b22da8cefa8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 17:14:56 +0900 Subject: [PATCH 264/355] Exit from match screen on escape --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 8 ++++++-- osu.Game/Screens/Multi/Match/MatchScreen.cs | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 1ec138ab57..576a1d619a 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -19,10 +19,10 @@ namespace osu.Game.Online.Chat /// public class StandAloneChatDisplay : CompositeDrawable { - private readonly bool postingTextbox; - public readonly Bindable Channel = new Bindable(); + public Action Exit; + private readonly FocusedTextBox textbox; protected ChannelManager ChannelManager; @@ -31,6 +31,8 @@ namespace osu.Game.Online.Chat private DrawableChannel drawableChannel; + private readonly bool postingTextbox; + private const float textbox_height = 30; /// @@ -66,6 +68,8 @@ namespace osu.Game.Online.Chat Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, }); + + textbox.Exit += () => Exit?.Invoke(); } Channel.BindValueChanged(channelChanged); diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index dbbdbb8c54..9f1bbfdb4e 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -28,6 +28,7 @@ namespace osu.Game.Screens.Multi.Match private readonly RoomBindings bindings = new RoomBindings(); private readonly MatchLeaderboard leaderboard; + private readonly Action pushGameplayScreen; [Cached] @@ -49,6 +50,7 @@ namespace osu.Game.Screens.Multi.Match bindings.Room = room; + MatchChatDisplay chat; Components.Header header; RoomSettingsOverlay settings; @@ -71,7 +73,7 @@ namespace osu.Game.Screens.Multi.Match new Drawable[] { leaderboard = new MatchLeaderboard(room) { RelativeSizeAxes = Axes.Both }, - new MatchChatDisplay(room) { RelativeSizeAxes = Axes.Both } + chat = new MatchChatDisplay(room) { RelativeSizeAxes = Axes.Both } }, }, } @@ -100,6 +102,8 @@ namespace osu.Game.Screens.Multi.Match else settings.Hide(); }; + + chat.Exit += Exit; } protected override void LoadComplete() From 2f32c4d4d1d4edb62a167746e7203d481773edff Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 17:17:51 +0900 Subject: [PATCH 265/355] Fix title of match song select --- osu.Game/Screens/Select/MatchSongSelect.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 2008c9b783..f5ce34ea25 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using Humanizer; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi; @@ -12,6 +13,7 @@ namespace osu.Game.Screens.Select public Action Selected; public string ShortTitle => "song selection"; + public override string Title => ShortTitle.Humanize(); protected override bool OnStart() { From 9542e3e24ada33a0d63030584b7c109f940a1ab3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Dec 2018 17:59:28 +0900 Subject: [PATCH 266/355] Add Updateable beatmap sprite --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- .../UpdateableBeatmapBackgroundSprite.cs | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c179821a7c..58c0819075 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// - public WorkingBeatmap DefaultBeatmap { private get; set; } + public WorkingBeatmap DefaultBeatmap { get; set; } public override string[] HandledExtensions => new[] { ".osz" }; diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs new file mode 100644 index 0000000000..1808325466 --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Beatmaps.Drawables +{ + /// + /// Display a baetmap background from a local source, but fallback to online source if not available. + /// + public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable + { + public readonly IBindable Beatmap = new Bindable(); + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + public UpdateableBeatmapBackgroundSprite() + { + Beatmap.BindValueChanged(b => Schedule(() => Model = b)); + } + + protected override Drawable CreateDrawable(BeatmapInfo model) + { + Drawable drawable; + + var localBeatmap = beatmaps.GetWorkingBeatmap(model); + + if (localBeatmap == beatmaps.DefaultBeatmap && model?.BeatmapSet?.OnlineInfo != null) + drawable = new BeatmapSetCover(model.BeatmapSet); + else + drawable = new BeatmapBackgroundSprite(localBeatmap); + + drawable.RelativeSizeAxes = Axes.Both; + drawable.Anchor = Anchor.Centre; + drawable.Origin = Anchor.Centre; + drawable.FillMode = FillMode.Fill; + + return drawable; + } + + protected override double FadeDuration => 400; + } +} From 1dd2a4e3680cd26eb1014f281220a3d698b8510f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 18:07:19 +0900 Subject: [PATCH 267/355] Fix host info not working --- .../Visual/TestCaseMatchHostInfo.cs | 10 +++++-- .../Multi/Match/Components/HostInfo.cs | 30 ++++++++++++------- .../Screens/Multi/Match/Components/Info.cs | 4 ++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs index 006af2e10e..8e733d388a 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; +using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; @@ -17,13 +17,19 @@ namespace osu.Game.Tests.Visual typeof(HostInfo) }; + private readonly Bindable host = new Bindable(new User { Username = "SomeHost" }); + public TestCaseMatchHostInfo() { - Child = new HostInfo(new Room { Host = { Value = new User { Username = "ImAHost" }}}) + HostInfo hostInfo; + + Child = hostInfo = new HostInfo { Anchor = Anchor.Centre, Origin = Anchor.Centre }; + + hostInfo.Host.BindTo(host); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index 01b84bd40b..437b4cfe1b 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -1,11 +1,11 @@ // 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.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; using osu.Game.Online.Chat; -using osu.Game.Online.Multiplayer; using osu.Game.Users; using osuTK; @@ -13,13 +13,16 @@ namespace osu.Game.Screens.Multi.Match.Components { public class HostInfo : CompositeDrawable { - public HostInfo(Room room) + public readonly IBindable Host = new Bindable(); + + private readonly LinkFlowContainer linkContainer; + private readonly UpdateableAvatar avatar; + + public HostInfo() { AutoSizeAxes = Axes.X; Height = 50; - LinkFlowContainer linkContainer; - InternalChild = new FillFlowContainer { AutoSizeAxes = Axes.Both, @@ -27,11 +30,7 @@ namespace osu.Game.Screens.Multi.Match.Components Spacing = new Vector2(5, 0), Children = new Drawable[] { - new UpdateableAvatar - { - Size = new Vector2(50), - User = room.Host.Value - }, + avatar = new UpdateableAvatar { Size = new Vector2(50) }, new FillFlowContainer { Anchor = Anchor.CentreLeft, @@ -43,11 +42,20 @@ namespace osu.Game.Screens.Multi.Match.Components } }; - if (room.Host.Value != null) + + + Host.BindValueChanged(updateHost); + } + + private void updateHost(User host) + { + avatar.User = host; + + if (host != null) { linkContainer.AddText("hosted by"); linkContainer.NewLine(); - linkContainer.AddLink(room.Host.Value.Username, null, LinkAction.OpenUserProfile, room.Host.Value.Id.ToString(), "View Profile", s => s.Font = "Exo2.0-BoldItalic"); + linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", s => s.Font = "Exo2.0-BoldItalic"); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index ca1ca5f40f..08ba370282 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -35,6 +35,7 @@ namespace osu.Game.Screens.Multi.Match.Components ViewBeatmapButton viewBeatmapButton; OsuSpriteText name; EndDateInfo endDate; + HostInfo hostInfo; Children = new Drawable[] { @@ -69,7 +70,7 @@ namespace osu.Game.Screens.Multi.Match.Components endDate = new EndDateInfo { TextSize = 14 } } }, - new HostInfo(room), + hostInfo = new HostInfo(), }, }, new FillFlowContainer @@ -95,6 +96,7 @@ namespace osu.Game.Screens.Multi.Match.Components viewBeatmapButton.Beatmap.BindTo(bindings.CurrentBeatmap); readyButton.Beatmap.BindTo(bindings.CurrentBeatmap); + hostInfo.Host.BindTo(bindings.Host); bindings.Availability.BindValueChanged(_ => updateAvailabilityStatus()); bindings.Status.BindValueChanged(_ => updateAvailabilityStatus()); From 6a5f0eca1813bc67b631da799b3f46fee5aa2fa6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 18:07:50 +0900 Subject: [PATCH 268/355] Fix various elements flashing --- osu.Game/Online/Multiplayer/Room.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 16b0c588fa..ef07fe4aa6 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -71,16 +71,25 @@ namespace osu.Game.Online.Multiplayer { RoomID.Value = other.RoomID; Name.Value = other.Name; - Host.Value = other.Host; - Status.Value = other.Status; + + if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id) + Host.Value = other.Host; + + if (Status.Value.GetType() != other.Status.Value.GetType()) + Status.Value = other.Status; + Availability.Value = other.Availability; - Type.Value = other.Type; + + if (Type.Value.GetType() != other.Type.Value.GetType()) + Type.Value = other.Type; + MaxParticipants.Value = other.MaxParticipants; Participants.Value = other.Participants.Value.ToArray(); EndDate.Value = other.EndDate; - Playlist.Clear(); - Playlist.AddRange(other.Playlist); + // Todo: Temporary, should only remove/add new items (requires framework changes) + if (Playlist.Count == 0) + Playlist.AddRange(other.Playlist); } public bool ShouldSerializeRoomID() => false; From 96c9e5f209bf6e9b8077997cd902a1a3987eb18d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 25 Dec 2018 18:34:45 +0900 Subject: [PATCH 269/355] Make DefaultBeatmap readonly --- osu.Game.Tests/Visual/TestCasePlaySongSelect.cs | 5 +---- osu.Game/Beatmaps/BeatmapManager.cs | 15 +++++++++------ osu.Game/OsuGameBase.cs | 9 ++++----- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index d87a8d0056..29060ceb12 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -87,10 +87,7 @@ namespace osu.Game.Tests.Visual usage.Migrate(); Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null) - { - DefaultBeatmap = defaultBeatmap = Beatmap.Default - }); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, null, defaultBeatmap = Beatmap.Default)); Beatmap.SetDefault(); } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 58c0819075..73fd5da22c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// - public WorkingBeatmap DefaultBeatmap { get; set; } + public readonly WorkingBeatmap DefaultBeatmap; public override string[] HandledExtensions => new[] { ".osz" }; @@ -77,16 +77,19 @@ namespace osu.Game.Beatmaps private readonly List currentDownloads = new List(); - public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null) + public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null, + WorkingBeatmap defaultBeatmap = null) : base(storage, contextFactory, new BeatmapStore(contextFactory), importHost) { - beatmaps = (BeatmapStore)ModelStore; - beatmaps.BeatmapHidden += b => BeatmapHidden?.Invoke(b); - beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); - this.rulesets = rulesets; this.api = api; this.audioManager = audioManager; + + DefaultBeatmap = defaultBeatmap; + + beatmaps = (BeatmapStore)ModelStore; + beatmaps.BeatmapHidden += b => BeatmapHidden?.Invoke(b); + beatmaps.BeatmapRestored += b => BeatmapRestored?.Invoke(b); } protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 0f1819d55b..002ef6ec32 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -153,9 +153,12 @@ namespace osu.Game dependencies.Cache(API); dependencies.CacheAs(API); + var defaultBeatmap = new DummyWorkingBeatmap(this); + beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); + 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(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap)); dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, BeatmapManager, Host.Storage, contextFactory, Host)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); @@ -166,10 +169,6 @@ namespace osu.Game fileImporters.Add(ScoreManager); fileImporters.Add(SkinManager); - var defaultBeatmap = new DummyWorkingBeatmap(this); - beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); - BeatmapManager.DefaultBeatmap = defaultBeatmap; - // tracks play so loud our samples can't keep up. // this adds a global reduction of track volume for the time being. Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); From c45c34d400003910f02638d359889222cc7fc3a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Dec 2018 19:17:21 +0900 Subject: [PATCH 270/355] Make beatmap importing possible elsewhere in tests --- .../Beatmaps/IO/ImportBeatmapTest.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 26167cb24a..c8fd531fcc 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Beatmaps.IO { try { - loadOszIntoOsu(loadOsu(host)); + LoadOszIntoOsu(loadOsu(host)); } finally { @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = loadOszIntoOsu(osu); + var imported = LoadOszIntoOsu(osu); deleteBeatmapSet(imported, osu); } @@ -69,8 +69,8 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = loadOszIntoOsu(osu); - var importedSecondTime = loadOszIntoOsu(osu); + var imported = LoadOszIntoOsu(osu); + var importedSecondTime = LoadOszIntoOsu(osu); // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. Assert.IsTrue(imported.ID == importedSecondTime.ID); @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Beatmaps.IO manager.ItemAdded += (_, __, ___) => fireCount++; manager.ItemRemoved += _ => fireCount++; - var imported = loadOszIntoOsu(osu); + var imported = LoadOszIntoOsu(osu); Assert.AreEqual(0, fireCount -= 1); @@ -160,12 +160,12 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); var manager = osu.Dependencies.Get(); - var imported = loadOszIntoOsu(osu); + var imported = LoadOszIntoOsu(osu); imported.Hash += "-changed"; manager.Update(imported); - var importedSecondTime = loadOszIntoOsu(osu); + var importedSecondTime = LoadOszIntoOsu(osu); Assert.IsTrue(imported.ID != importedSecondTime.ID); Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID); @@ -191,11 +191,11 @@ namespace osu.Game.Tests.Beatmaps.IO { var osu = loadOsu(host); - var imported = loadOszIntoOsu(osu); + var imported = LoadOszIntoOsu(osu); deleteBeatmapSet(imported, osu); - var importedSecondTime = loadOszIntoOsu(osu); + var importedSecondTime = LoadOszIntoOsu(osu); // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. Assert.IsTrue(imported.ID == importedSecondTime.ID); @@ -262,7 +262,7 @@ namespace osu.Game.Tests.Beatmaps.IO } } - private string createTemporaryBeatmap() + private static string createTemporaryBeatmap() { var temp = Path.GetTempFileName() + ".osz"; File.Copy(TEST_OSZ_PATH, temp, true); @@ -270,7 +270,7 @@ namespace osu.Game.Tests.Beatmaps.IO return temp; } - private BeatmapSetInfo loadOszIntoOsu(OsuGameBase osu, string path = null) + public static BeatmapSetInfo LoadOszIntoOsu(OsuGameBase osu, string path = null) { var temp = path ?? createTemporaryBeatmap(); @@ -305,7 +305,7 @@ namespace osu.Game.Tests.Beatmaps.IO return osu; } - private void ensureLoaded(OsuGameBase osu, int timeout = 60000) + private static void ensureLoaded(OsuGameBase osu, int timeout = 60000) { IEnumerable resultSets = null; var store = osu.Dependencies.Get(); @@ -343,7 +343,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(beatmap?.HitObjects.Any() == true); } - private void waitForOrAssert(Func result, string failureMessage, int timeout = 60000) + private static void waitForOrAssert(Func result, string failureMessage, int timeout = 60000) { Task task = Task.Run(() => { From c902c1587a8248d78ba6d6a13af78fc9674f4e9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Dec 2018 19:17:32 +0900 Subject: [PATCH 271/355] Add tests and modify fallback logic --- ...stCaseUpdateableBeatmapBackgroundSprite.cs | 51 +++++++++++++++++++ .../UpdateableBeatmapBackgroundSprite.cs | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs diff --git a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs new file mode 100644 index 0000000000..24701fccbc --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -0,0 +1,51 @@ +// 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.Configuration; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; +using osu.Game.Tests.Beatmaps.IO; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseUpdateableBeatmapBackgroundSprite : OsuTestCase + { + private UpdateableBeatmapBackgroundSprite backgroundSprite; + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osu, APIAccess api, RulesetStore rulesets) + { + Bindable beatmapBindable = new Bindable(); + + var imported = ImportBeatmapTest.LoadOszIntoOsu(osu); + + Child = backgroundSprite = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }; + + backgroundSprite.Beatmap.BindTo(beatmapBindable); + + var req = new GetBeatmapSetRequest(1); + api.Queue(req); + + AddStep("null", () => beatmapBindable.Value = null); + + AddStep("imported", () => beatmapBindable.Value = imported.Beatmaps.First()); + + if (api.IsLoggedIn) + AddUntilStep(() => req.Result != null, "wait for api response"); + + AddStep("online", () => beatmapBindable.Value = new BeatmapInfo + { + BeatmapSet = req.Result?.ToBeatmapSet(rulesets) + }); + } + } +} diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 1808325466..fd00576d21 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Drawables var localBeatmap = beatmaps.GetWorkingBeatmap(model); - if (localBeatmap == beatmaps.DefaultBeatmap && model?.BeatmapSet?.OnlineInfo != null) + if (localBeatmap.BeatmapInfo.ID == 0 && model?.BeatmapSet?.OnlineInfo != null) drawable = new BeatmapSetCover(model.BeatmapSet); else drawable = new BeatmapBackgroundSprite(localBeatmap); From 3370de3c2eedfb1a38a89285459dcfd8fdb432a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 11:53:24 +0900 Subject: [PATCH 272/355] Add rider live templates --- osu.sln.DotSettings | 121 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 112efb37f0..6b8e9dc808 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -673,6 +673,127 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste True True True + True + True + o!f – Object Initializer: Anchor&Origin + True + constant("Centre") + 0 + True + True + 2.0 + InCSharpFile + ofao + True + Anchor = Anchor.$anchor$, +Origin = Anchor.$anchor$, + True + True + o!f – InternalChildren = [] + True + True + 2.0 + InCSharpFile + ofic + True + InternalChildren = new Drawable[] +{ + $END$ +}; + True + True + o!f – new GridContainer { .. } + True + True + 2.0 + InCSharpFile + ofgc + True + new GridContainer +{ + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } +}; + True + True + o!f – new FillFlowContainer { .. } + True + True + 2.0 + InCSharpFile + offf + True + new FillFlowContainer +{ + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } +}, + True + True + o!f – new Container { .. } + True + True + 2.0 + InCSharpFile + ofcont + True + new Container +{ + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } +}, + True + True + o!f – BackgroundDependencyLoader load() + True + True + 2.0 + InCSharpFile + ofbdl + True + [BackgroundDependencyLoader] +private void load() +{ + $END$ +} + True + True + o!f – new Box { .. } + True + True + 2.0 + InCSharpFile + ofbox + True + new Box +{ + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, +}, + True + True + o!f – Children = [] + True + True + 2.0 + InCSharpFile + ofc + True + Children = new Drawable[] +{ + $END$ +}; True True True From e4a72c0c645103d0ee9b0553497459810fc04fa7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 13:18:36 +0900 Subject: [PATCH 273/355] Fix failing testcase --- osu.Game/Screens/Menu/ButtonSystem.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 943dfa53af..14eae54cb2 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -105,13 +105,13 @@ namespace osu.Game.Screens.Menu buttonArea.AddRange(buttonsTopLevel); } - [Resolved] + [Resolved(CanBeNull = true)] private OsuGame game { get; set; } [Resolved] private APIAccess api { get; set; } - [Resolved] + [Resolved(CanBeNull = true)] private NotificationOverlay notifications { get; set; } [BackgroundDependencyLoader(true)] @@ -128,7 +128,7 @@ namespace osu.Game.Screens.Menu { if (!api.IsLoggedIn) { - notifications.Post(new SimpleNotification + notifications?.Post(new SimpleNotification { Text = "You gotta be logged in to multi 'yo!", Icon = FontAwesome.fa_globe @@ -136,6 +136,7 @@ namespace osu.Game.Screens.Menu return; } + OnMulti?.Invoke(); } From e9556afe227f3b3ecd95ae049547d502d91d89d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 14:26:35 +0900 Subject: [PATCH 274/355] Don't use all uppercase (is applied automatically) --- .../Multi/Match/Components/RoomSettingsOverlay.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index 797894e93c..00ebb78c18 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -72,7 +72,7 @@ namespace osu.Game.Screens.Multi.Match.Components Padding = new MarginPadding { Right = field_padding / 2 }, Children = new[] { - new Section("ROOM NAME") + new Section("Room name") { Child = NameField = new SettingsTextBox { @@ -81,12 +81,12 @@ namespace osu.Game.Screens.Multi.Match.Components OnCommit = (sender, text) => apply(), }, }, - new Section("ROOM VISIBILITY") + new Section("Room visibility") { Alpha = disabled_alpha, Child = AvailabilityPicker = new RoomAvailabilityPicker(), }, - new Section("GAME TYPE") + new Section("Game type") { Alpha = disabled_alpha, Child = new FillFlowContainer @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Multi.Match.Components Padding = new MarginPadding { Left = field_padding / 2 }, Children = new[] { - new Section("MAX PARTICIPANTS") + new Section("Max participants") { Alpha = disabled_alpha, Child = MaxParticipantsField = new SettingsNumberTextBox @@ -127,7 +127,7 @@ namespace osu.Game.Screens.Multi.Match.Components OnCommit = (sender, text) => apply(), }, }, - new Section("DURATION") + new Section("Duration") { Child = DurationField = new DurationDropdown { @@ -148,7 +148,7 @@ namespace osu.Game.Screens.Multi.Match.Components } } }, - new Section("PASSWORD (OPTIONAL)") + new Section("Password (optional)") { Alpha = disabled_alpha, Child = PasswordField = new SettingsPasswordTextBox From 755c6b924396ee42ce6c25df26e8f4d04a23c760 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 15:03:35 +0900 Subject: [PATCH 275/355] Make room settings scroll --- .../Match/Components/RoomSettingsOverlay.cs | 173 +++++++++--------- 1 file changed, 91 insertions(+), 82 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index 00ebb78c18..cec4a20133 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -61,105 +61,113 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"28242d"), }, - new Container + new ScrollContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 35, Bottom = 75, Horizontal = SearchableListOverlay.WIDTH_PADDING }, Children = new[] { - new SectionContainer + new Container { - Padding = new MarginPadding { Right = field_padding / 2 }, - Children = new[] + Padding = new MarginPadding { Top = 35, Bottom = 75, Horizontal = SearchableListOverlay.WIDTH_PADDING }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - new Section("Room name") + new SectionContainer { - Child = NameField = new SettingsTextBox + Padding = new MarginPadding { Right = field_padding / 2 }, + Children = new[] { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), - }, - }, - new Section("Room visibility") - { - Alpha = disabled_alpha, - Child = AvailabilityPicker = new RoomAvailabilityPicker(), - }, - new Section("Game type") - { - Alpha = disabled_alpha, - Child = new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Spacing = new Vector2(7), - Children = new Drawable[] + new Section("Room name") { - TypePicker = new GameTypePicker + Child = NameField = new SettingsTextBox { RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + OnCommit = (sender, text) => apply(), }, - typeLabel = new OsuSpriteText + }, + new Section("Room visibility") + { + Alpha = disabled_alpha, + Child = AvailabilityPicker = new RoomAvailabilityPicker(), + }, + new Section("Game type") + { + Alpha = disabled_alpha, + Child = new FillFlowContainer { - TextSize = 14, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(7), + Children = new Drawable[] + { + TypePicker = new GameTypePicker + { + RelativeSizeAxes = Axes.X, + }, + typeLabel = new OsuSpriteText + { + TextSize = 14, + }, + }, + }, + }, + }, + }, + new SectionContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Padding = new MarginPadding { Left = field_padding / 2 }, + Children = new[] + { + new Section("Max participants") + { + Alpha = disabled_alpha, + Child = MaxParticipantsField = new SettingsNumberTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + OnCommit = (sender, text) => apply(), + }, + }, + new Section("Duration") + { + Child = DurationField = new DurationDropdown + { + RelativeSizeAxes = Axes.X, + Items = new[] + { + TimeSpan.FromMinutes(1), + TimeSpan.FromMinutes(30), + TimeSpan.FromHours(1), + TimeSpan.FromHours(2), + TimeSpan.FromHours(4), + TimeSpan.FromHours(8), + TimeSpan.FromHours(12), + TimeSpan.FromHours(16), + TimeSpan.FromHours(24), + TimeSpan.FromDays(3), + TimeSpan.FromDays(7) + } + } + }, + new Section("Password (optional)") + { + Alpha = disabled_alpha, + Child = PasswordField = new SettingsPasswordTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + OnCommit = (sender, text) => apply() }, }, }, }, }, - }, - new SectionContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Padding = new MarginPadding { Left = field_padding / 2 }, - Children = new[] - { - new Section("Max participants") - { - Alpha = disabled_alpha, - Child = MaxParticipantsField = new SettingsNumberTextBox - { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), - }, - }, - new Section("Duration") - { - Child = DurationField = new DurationDropdown - { - RelativeSizeAxes = Axes.X, - Items = new[] - { - TimeSpan.FromMinutes(1), - TimeSpan.FromMinutes(30), - TimeSpan.FromHours(1), - TimeSpan.FromHours(2), - TimeSpan.FromHours(4), - TimeSpan.FromHours(8), - TimeSpan.FromHours(12), - TimeSpan.FromHours(16), - TimeSpan.FromHours(24), - TimeSpan.FromDays(3), - TimeSpan.FromDays(7) - } - } - }, - new Section("Password (optional)") - { - Alpha = disabled_alpha, - Child = PasswordField = new SettingsPasswordTextBox - { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply() - }, - }, - }, - }, + } }, }, new Container @@ -265,7 +273,8 @@ namespace osu.Game.Screens.Multi.Match.Components { public SectionContainer() { - RelativeSizeAxes = Axes.Both; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; Width = 0.5f; Direction = FillDirection.Vertical; Spacing = new Vector2(field_padding); From 6e8c46f00bca239cfd0efa6deea08f92cf417a62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 15:23:57 +0900 Subject: [PATCH 276/355] Fix padding and use grid container for more correctness --- .../Match/Components/RoomSettingsOverlay.cs | 240 ++++++++++-------- 1 file changed, 130 insertions(+), 110 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs index cec4a20133..fc97edb103 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs @@ -61,136 +61,156 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"28242d"), }, - new ScrollContainer + new GridContainer { RelativeSizeAxes = Axes.Both, - Children = new[] + RowDimensions = new[] { - new Container + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - Padding = new MarginPadding { Top = 35, Bottom = 75, Horizontal = SearchableListOverlay.WIDTH_PADDING }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + new ScrollContainer { - new SectionContainer + Padding = new MarginPadding { Vertical = 10 }, + RelativeSizeAxes = Axes.Both, + Children = new[] { - Padding = new MarginPadding { Right = field_padding / 2 }, - Children = new[] + new Container { - new Section("Room name") + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - Child = NameField = new SettingsTextBox + new SectionContainer { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), - }, - }, - new Section("Room visibility") - { - Alpha = disabled_alpha, - Child = AvailabilityPicker = new RoomAvailabilityPicker(), - }, - new Section("Game type") - { - Alpha = disabled_alpha, - Child = new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Spacing = new Vector2(7), - Children = new Drawable[] + Padding = new MarginPadding { Right = field_padding / 2 }, + Children = new[] { - TypePicker = new GameTypePicker + new Section("Room name") { - RelativeSizeAxes = Axes.X, + Child = NameField = new SettingsTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + OnCommit = (sender, text) => apply(), + }, }, - typeLabel = new OsuSpriteText + new Section("Room visibility") { - TextSize = 14, + Alpha = disabled_alpha, + Child = AvailabilityPicker = new RoomAvailabilityPicker(), + }, + new Section("Game type") + { + Alpha = disabled_alpha, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(7), + Children = new Drawable[] + { + TypePicker = new GameTypePicker + { + RelativeSizeAxes = Axes.X, + }, + typeLabel = new OsuSpriteText + { + TextSize = 14, + }, + }, + }, + }, + }, + }, + new SectionContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Padding = new MarginPadding { Left = field_padding / 2 }, + Children = new[] + { + new Section("Max participants") + { + Alpha = disabled_alpha, + Child = MaxParticipantsField = new SettingsNumberTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + OnCommit = (sender, text) => apply(), + }, + }, + new Section("Duration") + { + Child = DurationField = new DurationDropdown + { + RelativeSizeAxes = Axes.X, + Items = new[] + { + TimeSpan.FromMinutes(1), + TimeSpan.FromMinutes(30), + TimeSpan.FromHours(1), + TimeSpan.FromHours(2), + TimeSpan.FromHours(4), + TimeSpan.FromHours(8), + TimeSpan.FromHours(12), + TimeSpan.FromHours(16), + TimeSpan.FromHours(24), + TimeSpan.FromDays(3), + TimeSpan.FromDays(7) + } + } + }, + new Section("Password (optional)") + { + Alpha = disabled_alpha, + Child = PasswordField = new SettingsPasswordTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + OnCommit = (sender, text) => apply() + }, }, }, }, }, - }, - }, - new SectionContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Padding = new MarginPadding { Left = field_padding / 2 }, - Children = new[] - { - new Section("Max participants") - { - Alpha = disabled_alpha, - Child = MaxParticipantsField = new SettingsNumberTextBox - { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), - }, - }, - new Section("Duration") - { - Child = DurationField = new DurationDropdown - { - RelativeSizeAxes = Axes.X, - Items = new[] - { - TimeSpan.FromMinutes(1), - TimeSpan.FromMinutes(30), - TimeSpan.FromHours(1), - TimeSpan.FromHours(2), - TimeSpan.FromHours(4), - TimeSpan.FromHours(8), - TimeSpan.FromHours(12), - TimeSpan.FromHours(16), - TimeSpan.FromHours(24), - TimeSpan.FromDays(3), - TimeSpan.FromDays(7) - } - } - }, - new Section("Password (optional)") - { - Alpha = disabled_alpha, - Child = PasswordField = new SettingsPasswordTextBox - { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply() - }, - }, - }, + } }, }, + }, + new Drawable[] + { + new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Y = 2, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), + }, + ApplyButton = new CreateRoomButton + { + Margin = new MarginPadding { Vertical = 20 }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(230, 55), + Action = apply, + }, + } + } } - }, - }, - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = 2, - RelativeSizeAxes = Axes.X, - Height = 60, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), - }, - ApplyButton = new CreateRoomButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(230, 35), - Action = apply, - }, } } }, From b2fb02709743d5db8e7446973224acedf18d3ff6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 15:26:46 +0900 Subject: [PATCH 277/355] Remove old testcase --- osu.Game.Tests/Visual/TestCaseRoomSettings.cs | 129 ------------------ 1 file changed, 129 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseRoomSettings.cs diff --git a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs b/osu.Game.Tests/Visual/TestCaseRoomSettings.cs deleted file mode 100644 index f44c7de721..0000000000 --- a/osu.Game.Tests/Visual/TestCaseRoomSettings.cs +++ /dev/null @@ -1,129 +0,0 @@ -// 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 NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Testing.Input; -using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Match.Components; -using osuTK.Input; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseRoomSettings : ManualInputManagerTestCase - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(RoomSettingsOverlay), - typeof(GameTypePicker) - }; - - private readonly Room room; - private readonly TestRoomSettingsOverlay overlay; - - public TestCaseRoomSettings() - { - room = new Room - { - Name = { Value = "One Testing Room" }, - Availability = { Value = RoomAvailability.Public }, - Type = { Value = new GameTypeTeamVersus() }, - MaxParticipants = { Value = 10 }, - }; - - Add(overlay = new TestRoomSettingsOverlay(new Room()) - { - RelativeSizeAxes = Axes.Both, - Height = 0.75f, - State = Visibility.Visible - }); - - assertAll(); - AddStep(@"set name", () => overlay.CurrentName = @"Two Testing Room"); - AddStep(@"set max", () => overlay.CurrentMaxParticipants = null); - AddStep(@"set availability", () => overlay.CurrentAvailability = RoomAvailability.InviteOnly); - AddStep(@"set type", () => overlay.CurrentType = new GameTypeTagTeam()); - apply(); - assertAll(); - AddStep(@"show", overlay.Show); - AddStep(@"set room name", () => room.Name.Value = @"Room Changed Name!"); - AddStep(@"set room availability", () => room.Availability.Value = RoomAvailability.Public); - AddStep(@"set room type", () => room.Type.Value = new GameTypeTag()); - AddStep(@"set room max", () => room.MaxParticipants.Value = 100); - assertAll(); - AddStep(@"set name", () => overlay.CurrentName = @"Unsaved Testing Room"); - AddStep(@"set max", () => overlay.CurrentMaxParticipants = 20); - AddStep(@"set availability", () => overlay.CurrentAvailability = RoomAvailability.FriendsOnly); - AddStep(@"set type", () => overlay.CurrentType = new GameTypeVersus()); - AddStep(@"hide", overlay.Hide); - AddWaitStep(5); - AddStep(@"show", overlay.Show); - assertAll(); - AddStep(@"hide", overlay.Hide); - } - - private void apply() - { - AddStep(@"apply", () => - { - overlay.ClickApplyButton(InputManager); - }); - } - - private void assertAll() - { - AddAssert(@"name == room name", () => overlay.CurrentName == room.Name.Value); - AddAssert(@"max == room max", () => overlay.CurrentMaxParticipants == room.MaxParticipants.Value); - AddAssert(@"availability == room availability", () => overlay.CurrentAvailability == room.Availability.Value); - AddAssert(@"type == room type", () => Equals(overlay.CurrentType, room.Type.Value)); - } - - private class TestRoomSettingsOverlay : RoomSettingsOverlay - { - public TestRoomSettingsOverlay(Room room) - : base(room) - { - } - - public string CurrentName - { - get => NameField.Text; - set => NameField.Text = value; - } - - public int? CurrentMaxParticipants - { - get - { - if (int.TryParse(MaxParticipantsField.Text, out int max)) - return max; - - return null; - } - set => MaxParticipantsField.Text = value?.ToString(); - } - - public RoomAvailability CurrentAvailability - { - get => AvailabilityPicker.Current.Value; - set => AvailabilityPicker.Current.Value = value; - } - - public GameType CurrentType - { - get => TypePicker.Current.Value; - set => TypePicker.Current.Value = value; - } - - public void ClickApplyButton(ManualInputManager inputManager) - { - inputManager.MoveMouseTo(ApplyButton); - inputManager.Click(MouseButton.Left); - } - } - } -} From aeb2186539bb1cd62971b02ff9839482a9955e3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 16:06:39 +0900 Subject: [PATCH 278/355] Fix api get user request never failing --- osu.Game/Online/API/APIAccess.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 8038c1fc1f..10b4e73419 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -145,7 +145,8 @@ namespace osu.Game.Online.API if (!handleRequest(userReq)) { - Thread.Sleep(500); + if (State == APIState.Connecting) + State = APIState.Failing; continue; } From a8d0ff67a9bf0ad5e469430131999a2c630f3771 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 16:04:05 +0900 Subject: [PATCH 279/355] Add automated match settings overlay tests --- .../Visual/TestCaseMatchSettingsOverlay.cs | 93 ++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index fede2f509f..f4934e2a7d 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -3,9 +3,16 @@ using System; using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Match.Components; namespace osu.Game.Tests.Visual @@ -17,13 +24,95 @@ namespace osu.Game.Tests.Visual typeof(RoomSettingsOverlay) }; - public TestCaseMatchSettingsOverlay() + [Cached(Type = typeof(IRoomManager))] + private TestRoomManager roomManager = new TestRoomManager(); + + private Room room; + private TestRoomSettings settings; + + [SetUp] + public void Setup() => Schedule(() => { - Child = new RoomSettingsOverlay(new Room()) + room = new Room(); + settings = new TestRoomSettings(room) { RelativeSizeAxes = Axes.Both, State = Visibility.Visible }; + + Child = settings; + }); + + [Test] + public void TestButtonEnabledOnlyWithNameAndBeatmap() + { + AddStep("clear name and beatmap", () => + { + room.Name.Value = ""; + room.Playlist.Clear(); + }); + + AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + + AddStep("set name", () => room.Name.Value = "Room name"); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + + AddStep("set beatmap", () => room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo })); + AddAssert("button enabled", () => settings.ApplyButton.Enabled); + + AddStep("clear name", () => room.Name.Value = ""); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + } + + [Test] + public void TestCorrectSettingsApplied() + { + const string expected_name = "expected name"; + TimeSpan expectedDuration = TimeSpan.FromMinutes(15); + + Room createdRoom = null; + + AddStep("setup", () => + { + settings.NameField.Current.Value = expected_name; + settings.DurationField.Current.Value = expectedDuration; + + roomManager.CreateRequested = r => createdRoom = r; + }); + + AddStep("create room", () => settings.ApplyButton.Action.Invoke()); + AddAssert("has correct name", () => createdRoom.Name.Value == expected_name); + AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration); + } + + private class TestRoomSettings : RoomSettingsOverlay + { + public new TriangleButton ApplyButton => base.ApplyButton; + + public new OsuTextBox NameField => base.NameField; + public new OsuDropdown DurationField => base.DurationField; + + public TestRoomSettings(Room room) + : base(room) + { + } + } + + private class TestRoomManager : IRoomManager + { + public Action CreateRequested; + + public event Action OpenRequested; + + public IBindableCollection Rooms { get; } = null; + + public void CreateRoom(Room room) => CreateRequested?.Invoke(room); + + public void JoinRoom(Room room) => throw new NotImplementedException(); + + public void PartRoom() => throw new NotImplementedException(); + + public void Filter(FilterCriteria criteria) => throw new NotImplementedException(); } } } From 9b2575cc202dfe3fa7812a213ec6f356a980ab18 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 16:11:40 +0900 Subject: [PATCH 280/355] RoomSettingsOverlay -> MatchSettingOverlay --- osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs | 4 ++-- osu.Game/Online/Multiplayer/Room.cs | 2 +- osu.Game/Screens/Multi/Match/Components/Header.cs | 4 ++-- .../{RoomSettingsOverlay.cs => MatchSettingsOverlay.cs} | 4 ++-- osu.Game/Screens/Multi/Match/MatchScreen.cs | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) rename osu.Game/Screens/Multi/Match/Components/{RoomSettingsOverlay.cs => MatchSettingsOverlay.cs} (99%) diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index f4934e2a7d..322ff5bc07 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { - typeof(RoomSettingsOverlay) + typeof(MatchSettingsOverlay) }; [Cached(Type = typeof(IRoomManager))] @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration); } - private class TestRoomSettings : RoomSettingsOverlay + private class TestRoomSettings : MatchSettingsOverlay { public new TriangleButton ApplyButton => base.ApplyButton; diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index ef07fe4aa6..3bad25f716 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -16,7 +16,7 @@ namespace osu.Game.Online.Multiplayer public Bindable RoomID { get; private set; } = new Bindable(); [JsonProperty("name")] - public Bindable Name { get; private set; } = new Bindable("My awesome room!"); + public Bindable Name { get; private set; } = new Bindable(); [JsonProperty("host")] public Bindable Host { get; private set; } = new Bindable(); diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index b2d39151c1..4feca7dccb 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -94,11 +94,11 @@ namespace osu.Game.Screens.Multi.Match.Components Origin = Anchor.TopRight, RelativeSizeAxes = Axes.Y, Width = 200, - Padding = new MarginPadding { Vertical = 5 }, + Padding = new MarginPadding { Vertical = 10 }, Child = beatmapButton = new BeatmapSelectButton(room) { RelativeSizeAxes = Axes.Both, - Height = 1 + Height = 1, }, }, Tabs = new MatchTabControl(room) diff --git a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs similarity index 99% rename from osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs rename to osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index fc97edb103..6de2bed938 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Multi.Match.Components { - public class RoomSettingsOverlay : FocusedOverlayContainer + public class MatchSettingsOverlay : FocusedOverlayContainer { private const float transition_duration = 350; private const float field_padding = 45; @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Multi.Match.Components [Resolved(CanBeNull = true)] private IRoomManager manager { get; set; } - public RoomSettingsOverlay(Room room) + public MatchSettingsOverlay(Room room) { this.room = room; diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 9f1bbfdb4e..eb7a206163 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Multi.Match MatchChatDisplay chat; Components.Header header; - RoomSettingsOverlay settings; + MatchSettingsOverlay settings; Children = new Drawable[] { @@ -90,7 +90,7 @@ namespace osu.Game.Screens.Multi.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Components.Header.HEIGHT }, - Child = settings = new RoomSettingsOverlay(room) { RelativeSizeAxes = Axes.Both }, + Child = settings = new MatchSettingsOverlay(room) { RelativeSizeAxes = Axes.Both }, }, }; From c6c8c472bb1f7f93a4551c2017473a082474686d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 16:46:50 +0900 Subject: [PATCH 281/355] Split class out --- osu.Game.Tests/Visual/TestCaseMatchHeader.cs | 3 +- osu.Game/Online/Multiplayer/GameType.cs | 152 ------------------ .../Multiplayer/GameTypes/GameTypeTag.cs | 24 +++ .../Multiplayer/GameTypes/GameTypeTagTeam.cs | 41 +++++ .../GameTypes/GameTypeTeamVersus.cs | 29 ++++ .../GameTypes/GameTypeTimeshift.cs | 22 +++ .../Multiplayer/GameTypes/GameTypeVersus.cs | 19 +++ osu.Game/Online/Multiplayer/Room.cs | 1 + osu.Game/Online/Multiplayer/VersusRow.cs | 52 ++++++ .../Multi/Match/Components/GameTypePicker.cs | 1 + osu.Game/Screens/Multi/Match/MatchScreen.cs | 3 +- osu.Game/Screens/Multi/Multiplayer.cs | 11 +- 12 files changed, 201 insertions(+), 157 deletions(-) create mode 100644 osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs create mode 100644 osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs create mode 100644 osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs create mode 100644 osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs create mode 100644 osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs create mode 100644 osu.Game/Online/Multiplayer/VersusRow.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs index ac964e22a6..4c8cdbfd19 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . +// 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 osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi.Match.Components; diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs index 8c9d635eea..e800142f9b 100644 --- a/osu.Game/Online/Multiplayer/GameType.cs +++ b/osu.Game/Online/Multiplayer/GameType.cs @@ -1,11 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osuTK; -using osuTK.Graphics; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; namespace osu.Game.Online.Multiplayer @@ -19,152 +15,4 @@ namespace osu.Game.Online.Multiplayer public override int GetHashCode() => GetType().GetHashCode(); public override bool Equals(object obj) => GetType() == obj?.GetType(); } - - public class GameTypeTag : GameType - { - public override string Name => "Tag"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = FontAwesome.fa_refresh, - Size = new Vector2(size), - Colour = colours.Blue, - Shadow = false, - }; - } - } - - public class GameTypeVersus : GameType - { - public override string Name => "Versus"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new VersusRow(colours.Blue, colours.Blue, size * 0.6f) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; - } - } - - public class GameTypeTagTeam : GameType - { - public override string Name => "Tag Team"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(2f), - Children = new[] - { - new SpriteIcon - { - Icon = FontAwesome.fa_refresh, - Size = new Vector2(size * 0.75f), - Colour = colours.Blue, - Shadow = false, - }, - new SpriteIcon - { - Icon = FontAwesome.fa_refresh, - Size = new Vector2(size * 0.75f), - Colour = colours.Pink, - Shadow = false, - }, - }, - }; - } - } - - public class GameTypeTeamVersus : GameType - { - public override string Name => "Team Versus"; - - public override Drawable GetIcon(OsuColour colours, float size) - { - return new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(2f), - Children = new[] - { - new VersusRow(colours.Blue, colours.Pink, size * 0.5f), - new VersusRow(colours.Blue, colours.Pink, size * 0.5f), - }, - }; - } - } - - public class VersusRow : FillFlowContainer - { - public VersusRow(Color4 first, Color4 second, float size) - { - var triangleSize = new Vector2(size); - AutoSizeAxes = Axes.Both; - Spacing = new Vector2(2f, 0f); - - Children = new[] - { - new Container - { - Size = triangleSize, - Colour = first, - Children = new[] - { - new EquilateralTriangle - { - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, - Rotation = 90, - EdgeSmoothness = new Vector2(1f), - }, - }, - }, - new Container - { - Size = triangleSize, - Colour = second, - Children = new[] - { - new EquilateralTriangle - { - Anchor = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, - Rotation = -90, - EdgeSmoothness = new Vector2(1f), - }, - }, - }, - }; - } - } - - public class GameTypeTimeshift : GameType - { - public override string Name => "Timeshift"; - - public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Icon = FontAwesome.fa_osu_charts, - X = -2, // The icon is off-centre - Size = new Vector2(size), - Colour = colours.Blue, - Shadow = false - }; - } } diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs new file mode 100644 index 0000000000..d31439f0fe --- /dev/null +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs @@ -0,0 +1,24 @@ +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osuTK; + +namespace osu.Game.Online.Multiplayer.GameTypes +{ + public class GameTypeTag : GameType + { + public override string Name => "Tag"; + + public override Drawable GetIcon(OsuColour colours, float size) + { + return new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.fa_refresh, + Size = new Vector2(size), + Colour = colours.Blue, + Shadow = false, + }; + } + } +} \ No newline at end of file diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs new file mode 100644 index 0000000000..74c8e76b46 --- /dev/null +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs @@ -0,0 +1,41 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osuTK; + +namespace osu.Game.Online.Multiplayer.GameTypes +{ + public class GameTypeTagTeam : GameType + { + public override string Name => "Tag Team"; + + public override Drawable GetIcon(OsuColour colours, float size) + { + return new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(2f), + Children = new[] + { + new SpriteIcon + { + Icon = FontAwesome.fa_refresh, + Size = new Vector2(size * 0.75f), + Colour = colours.Blue, + Shadow = false, + }, + new SpriteIcon + { + Icon = FontAwesome.fa_refresh, + Size = new Vector2(size * 0.75f), + Colour = colours.Pink, + Shadow = false, + }, + }, + }; + } + } +} \ No newline at end of file diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs new file mode 100644 index 0000000000..74c2c00c3b --- /dev/null +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs @@ -0,0 +1,29 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osuTK; + +namespace osu.Game.Online.Multiplayer.GameTypes +{ + public class GameTypeTeamVersus : GameType + { + public override string Name => "Team Versus"; + + public override Drawable GetIcon(OsuColour colours, float size) + { + return new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(2f), + Children = new[] + { + new VersusRow(colours.Blue, colours.Pink, size * 0.5f), + new VersusRow(colours.Blue, colours.Pink, size * 0.5f), + }, + }; + } + } +} \ No newline at end of file diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs new file mode 100644 index 0000000000..e8aa82d022 --- /dev/null +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs @@ -0,0 +1,22 @@ +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osuTK; + +namespace osu.Game.Online.Multiplayer.GameTypes +{ + public class GameTypeTimeshift : GameType + { + public override string Name => "Timeshift"; + + public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.fa_clock_o, + X = -2, // The icon is off-centre + Size = new Vector2(size), + Colour = colours.Blue, + Shadow = false + }; + } +} \ No newline at end of file diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs new file mode 100644 index 0000000000..b6d832490f --- /dev/null +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs @@ -0,0 +1,19 @@ +using osu.Framework.Graphics; +using osu.Game.Graphics; + +namespace osu.Game.Online.Multiplayer.GameTypes +{ + public class GameTypeVersus : GameType + { + public override string Name => "Versus"; + + public override Drawable GetIcon(OsuColour colours, float size) + { + return new VersusRow(colours.Blue, colours.Blue, size * 0.6f) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + } +} \ No newline at end of file diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 3bad25f716..b17d08320c 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; +using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Users; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Multiplayer/VersusRow.cs b/osu.Game/Online/Multiplayer/VersusRow.cs new file mode 100644 index 0000000000..3c7ebd936e --- /dev/null +++ b/osu.Game/Online/Multiplayer/VersusRow.cs @@ -0,0 +1,52 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Online.Multiplayer +{ + public class VersusRow : FillFlowContainer + { + public VersusRow(Color4 first, Color4 second, float size) + { + var triangleSize = new Vector2(size); + AutoSizeAxes = Axes.Both; + Spacing = new Vector2(2f, 0f); + + Children = new[] + { + new Container + { + Size = triangleSize, + Colour = first, + Children = new[] + { + new EquilateralTriangle + { + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Rotation = 90, + EdgeSmoothness = new Vector2(1f), + }, + }, + }, + new Container + { + Size = triangleSize, + Colour = second, + Children = new[] + { + new EquilateralTriangle + { + Anchor = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Rotation = -90, + EdgeSmoothness = new Vector2(1f), + }, + }, + }, + }; + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs index aec26a751e..caf686165f 100644 --- a/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Screens.Multi.Components; using osuTK; diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index eb7a206163..7892c335b6 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; @@ -22,7 +23,7 @@ namespace osu.Game.Screens.Multi.Match public class MatchScreen : MultiplayerScreen { public override bool AllowBeatmapRulesetChange => false; - public override string Title => room.Name.Value; + public override string Title => room.RoomID.Value == null ? "New room" : room.Name.Value; public override string ShortTitle => "room"; private readonly RoomBindings bindings = new RoomBindings(); diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 7a8f9f3948..b9b86fbfc7 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Screens.Menu; @@ -34,6 +35,9 @@ namespace osu.Game.Screens.Multi [Cached(Type = typeof(IRoomManager))] private RoomManager roomManager; + [Resolved] + private APIAccess api { get; set; } + public Multiplayer() { Child = waves = new MultiplayerWaveContainer @@ -82,13 +86,14 @@ namespace osu.Game.Screens.Multi Right = 10, }, Text = "Create room", - Action = () => loungeScreen.Open(new Room()) + Action = () => loungeScreen.Open(new Room + { + Name = { Value = $"{api.LocalUser}'s awesome room" } + }), }, roomManager = new RoomManager() }); - screenAdded(loungeScreen); - loungeScreen.Exited += s => Exit(); } From f442e5962059048fb929b993224b95bf5ef3f5f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 17:07:59 +0900 Subject: [PATCH 282/355] Icon and beatmap title visual pass --- .../Multiplayer/GameTypes/GameTypeTimeshift.cs | 3 +-- .../Multiplayer/{ => GameTypes}/VersusRow.cs | 2 +- osu.Game/Screens/Multi/Components/BeatmapTitle.cs | 15 +++++++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) rename osu.Game/Online/Multiplayer/{ => GameTypes}/VersusRow.cs (96%) diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs index e8aa82d022..e87f8a9696 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs @@ -13,10 +13,9 @@ namespace osu.Game.Online.Multiplayer.GameTypes Anchor = Anchor.Centre, Origin = Anchor.Centre, Icon = FontAwesome.fa_clock_o, - X = -2, // The icon is off-centre Size = new Vector2(size), Colour = colours.Blue, Shadow = false }; } -} \ No newline at end of file +} diff --git a/osu.Game/Online/Multiplayer/VersusRow.cs b/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs similarity index 96% rename from osu.Game/Online/Multiplayer/VersusRow.cs rename to osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs index 3c7ebd936e..2b150fc6f0 100644 --- a/osu.Game/Online/Multiplayer/VersusRow.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics.Shapes; using osuTK; using osuTK.Graphics; -namespace osu.Game.Online.Multiplayer +namespace osu.Game.Online.Multiplayer.GameTypes { public class VersusRow : FillFlowContainer { diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index d609f7a70d..b58af398ca 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -1,11 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; @@ -23,14 +25,12 @@ namespace osu.Game.Screens.Multi.Components AutoSizeAxes = Axes.Both; InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both }; - - Beatmap.BindValueChanged(v => updateText()); } protected override void LoadComplete() { base.LoadComplete(); - updateText(); + Beatmap.BindValueChanged(v => updateText(), true); } private float textSize = OsuSpriteText.FONT_SIZE; @@ -48,6 +48,9 @@ namespace osu.Game.Screens.Multi.Components } } + [Resolved] + private OsuColour colours { get; set; } + private void updateText() { if (!IsLoaded) @@ -56,7 +59,11 @@ namespace osu.Game.Screens.Multi.Components textFlow.Clear(); if (Beatmap.Value == null) - textFlow.AddText("Changing map", s => s.TextSize = TextSize); + textFlow.AddText("No beatmap selected", s => + { + s.TextSize = TextSize; + s.Colour = colours.PinkLight; + }); else { textFlow.AddLink(new[] From 63847890d15e64be77da4e4ecf9329711d8e392f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 18:05:12 +0900 Subject: [PATCH 283/355] Add better messaging when connecting or failing --- .../Graphics/Containers/LinkFlowContainer.cs | 21 ++++++++++++-- .../Sections/General/LoginSettings.cs | 29 +++++++++++-------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 54a2ea47f9..74315d2522 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; +using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -61,11 +62,25 @@ namespace osu.Game.Graphics.Containers } public void AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); + + public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); + + public void AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) { - AddInternal(new DrawableLinkCompiler(AddText(text, creationParameters).ToList()) + foreach (var t in text) + AddArbitraryDrawable(t); + + createLink(text, null, url, linkType, linkArgument, tooltipText); + } + + private void createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) + { + AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = () => + Action = action ?? (() => { switch (linkType) { @@ -104,7 +119,7 @@ namespace osu.Game.Graphics.Containers default: throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); } - }, + }), }); } } diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 0cb6d2d1aa..163eced103 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; using RectangleF = osu.Framework.Graphics.Primitives.RectangleF; using Container = osu.Framework.Graphics.Containers.Container; @@ -86,25 +87,29 @@ namespace osu.Game.Overlays.Settings.Sections.General }; break; case APIState.Failing: - Children = new Drawable[] - { - new OsuSpriteText - { - Text = "Connection failing :(", - }, - }; - break; case APIState.Connecting: + LinkFlowContainer linkFlow; + Children = new Drawable[] { - new OsuSpriteText + new LoadingAnimation { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = "Connecting...", + State = Visibility.Visible, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + linkFlow = new LinkFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Text = state == APIState.Failing ? "Connection is failing, will attempt to reconnect... " : "Attempting to connect... ", Margin = new MarginPadding { Top = 10, Bottom = 10 }, }, }; + + linkFlow.AddLink("cancel", api.Logout, string.Empty); break; case APIState.Online: Children = new Drawable[] From edfb027ff274fc50c67c3d9204bfd3ce4067abf3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 18:49:33 +0900 Subject: [PATCH 284/355] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 18addaefb6..103c7c20d6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 0cefd4b21dc299309bda76968f3f3d7e4cfbfe25 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 19:14:15 +0900 Subject: [PATCH 285/355] Improve room padding --- osu.Game/Screens/Multi/Lounge/LoungeScreen.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs index 82d593033f..cb8591be9e 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs @@ -47,11 +47,8 @@ namespace osu.Game.Screens.Multi.Lounge { RelativeSizeAxes = Axes.Both, Width = 0.55f, - Padding = new MarginPadding - { - Vertical = 35 - DrawableRoom.SELECTION_BORDER_WIDTH, - Right = 20 - DrawableRoom.SELECTION_BORDER_WIDTH - }, + ScrollbarOverlapsContent = false, + Padding = new MarginPadding(10), Child = new SearchContainer { RelativeSizeAxes = Axes.X, @@ -140,7 +137,7 @@ namespace osu.Game.Screens.Multi.Lounge if (!IsCurrentScreen) return; - Push(new MatchScreen(room, s => pushGameplayScreen?.Invoke(s))); + Push(new MatchScreen(room, s => pushGameplayScreen?.Invoke(s))); } protected override void Dispose(bool isDisposing) From 532a970c0fbcd20584b70c5e00c4edeca8db8775 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 19:20:54 +0900 Subject: [PATCH 286/355] Give leaderboard and chat more breathing room --- osu.Game/Screens/Multi/Match/MatchScreen.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index 7892c335b6..c784a27b99 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -73,8 +73,20 @@ namespace osu.Game.Screens.Multi.Match { new Drawable[] { - leaderboard = new MatchLeaderboard(room) { RelativeSizeAxes = Axes.Both }, - chat = new MatchChatDisplay(room) { RelativeSizeAxes = Axes.Both } + leaderboard = new MatchLeaderboard(room) + { + Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.Both + }, + new Container + { + Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.Both, + Child = chat = new MatchChatDisplay(room) + { + RelativeSizeAxes = Axes.Both + } + }, }, }, } From 2353c204ee502365a6684949c53887ae321c95d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:05:57 +0900 Subject: [PATCH 287/355] Renaming --- .../Visual/TestCaseLoungeRoomsContainer.cs | 4 +-- .../Visual/TestCaseMatchSettingsOverlay.cs | 2 +- osu.Game.Tests/Visual/TestCaseMultiHeader.cs | 8 +++--- osu.Game.Tests/Visual/TestCaseMultiResults.cs | 10 +++---- osu.Game.Tests/Visual/TestCaseMultiScreen.cs | 2 +- osu.Game/Screens/Multi/Header.cs | 2 +- ...ayerScreen.cs => IMultiplayerSubScreen.cs} | 2 +- osu.Game/Screens/Multi/IRoomManager.cs | 4 +-- .../{LoungeScreen.cs => LoungeSubScreen.cs} | 13 +++++----- .../{MatchScreen.cs => MatchSubScreen.cs} | 10 +++++-- osu.Game/Screens/Multi/Multiplayer.cs | 26 +++++++++++-------- ...layerScreen.cs => MultiplayerSubScreen.cs} | 2 +- .../Screens/Multi/Play/TimeshiftPlayer.cs | 2 +- .../{MultiResults.cs => MatchResults.cs} | 4 +-- osu.Game/Screens/Multi/RoomManager.cs | 4 +-- osu.Game/Screens/Select/MatchSongSelect.cs | 2 +- 16 files changed, 54 insertions(+), 43 deletions(-) rename osu.Game/Screens/Multi/{IMultiplayerScreen.cs => IMultiplayerSubScreen.cs} (84%) rename osu.Game/Screens/Multi/Lounge/{LoungeScreen.cs => LoungeSubScreen.cs} (92%) rename osu.Game/Screens/Multi/Match/{MatchScreen.cs => MatchSubScreen.cs} (95%) rename osu.Game/Screens/Multi/{MultiplayerScreen.cs => MultiplayerSubScreen.cs} (95%) rename osu.Game/Screens/Multi/Ranking/{MultiResults.cs => MatchResults.cs} (89%) diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index 916468ae2f..dd7e8f7fac 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -71,14 +71,14 @@ namespace osu.Game.Tests.Visual private class TestRoomManager : IRoomManager { - public event Action OpenRequested; + public event Action RoomJoined; public readonly BindableCollection Rooms = new BindableCollection(); IBindableCollection IRoomManager.Rooms => Rooms; public void CreateRoom(Room room) => Rooms.Add(room); - public void JoinRoom(Room room) => OpenRequested?.Invoke(room); + public void JoinRoom(Room room) => RoomJoined?.Invoke(room); public void PartRoom() { diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index 322ff5bc07..3c41fd6920 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual { public Action CreateRequested; - public event Action OpenRequested; + public event Action RoomJoined; public IBindableCollection Rooms { get; } = null; diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs index 2005c707b1..602108d078 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiHeader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual { int index = 0; - OsuScreen currentScreen = new TestMultiplayerScreen(index); + OsuScreen currentScreen = new TestMultiplayerSubScreen(index); Children = new Drawable[] { @@ -23,16 +23,16 @@ namespace osu.Game.Tests.Visual new Header(currentScreen) }; - AddStep("push multi screen", () => currentScreen.Push(currentScreen = new TestMultiplayerScreen(++index))); + AddStep("push multi screen", () => currentScreen.Push(currentScreen = new TestMultiplayerSubScreen(++index))); } - private class TestMultiplayerScreen : OsuScreen, IMultiplayerScreen + private class TestMultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen { private readonly int index; public string ShortTitle => $"Screen {index}"; - public TestMultiplayerScreen(int index) + public TestMultiplayerSubScreen(int index) { this.index = index; } diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMultiResults.cs index 38027e0bc3..8991782835 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiResults.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiResults.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { - typeof(MultiResults), + typeof(MatchResults), typeof(RoomLeaderboardPageInfo), typeof(RoomRankingResultsPage) }; @@ -38,22 +38,22 @@ namespace osu.Game.Tests.Visual if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); - Child = new TestMultiResults(new ScoreInfo + Child = new TestMatchResults(new ScoreInfo { User = new User { Id = 10 }, }); } - private class TestMultiResults : MultiResults + private class TestMatchResults : MatchResults { private readonly Room room; - public TestMultiResults(ScoreInfo score) + public TestMatchResults(ScoreInfo score) : this(score, new Room()) { } - public TestMultiResults(ScoreInfo score, Room room) + public TestMatchResults(ScoreInfo score, Room room) : base(score, room) { this.room = room; diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs index c65ab4e3e3..88265d146f 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(Multiplayer), - typeof(LoungeScreen), + typeof(LoungeSubScreen), typeof(FilterControl) }; diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 849be44f4f..2849fd89e0 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Multi breadcrumbs.Current.ValueChanged += s => { - if (s is IMultiplayerScreen mpScreen) + if (s is IMultiplayerSubScreen mpScreen) screenType.Text = mpScreen.ShortTitle.ToLowerInvariant(); }; diff --git a/osu.Game/Screens/Multi/IMultiplayerScreen.cs b/osu.Game/Screens/Multi/IMultiplayerSubScreen.cs similarity index 84% rename from osu.Game/Screens/Multi/IMultiplayerScreen.cs rename to osu.Game/Screens/Multi/IMultiplayerSubScreen.cs index c1f43fa30d..4796ffc05c 100644 --- a/osu.Game/Screens/Multi/IMultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/IMultiplayerSubScreen.cs @@ -3,7 +3,7 @@ namespace osu.Game.Screens.Multi { - public interface IMultiplayerScreen + public interface IMultiplayerSubScreen { string ShortTitle { get; } } diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index f09f360ea2..b94df93581 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -11,9 +11,9 @@ namespace osu.Game.Screens.Multi public interface IRoomManager { /// - /// Invoked when this requests a to be opened. + /// Invoked when a room is joined. /// - event Action OpenRequested; + event Action RoomJoined; /// /// All the active s. diff --git a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs similarity index 92% rename from osu.Game/Screens/Multi/Lounge/LoungeScreen.cs rename to osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index cb8591be9e..c49cfc6b9c 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.Multi.Match; namespace osu.Game.Screens.Multi.Lounge { - public class LoungeScreen : MultiplayerScreen + public class LoungeSubScreen : MultiplayerSubScreen { protected readonly FilterControl Filter; @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Multi.Lounge protected override Drawable TransitionContent => content; - public LoungeScreen(Action pushGameplayScreen) + public LoungeSubScreen(Action pushGameplayScreen) { this.pushGameplayScreen = pushGameplayScreen; @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Multi.Lounge private void load() { if (roomManager != null) - roomManager.OpenRequested += Open; + roomManager.RoomJoined += Open; } protected override void UpdateAfterChildren() @@ -109,7 +109,8 @@ namespace osu.Game.Screens.Multi.Lounge roomManager?.PartRoom(); Filter.Search.HoldFocus = false; - return base.OnExiting(next); + // no base call; don't animate + return false; } protected override void OnResuming(Screen last) @@ -137,7 +138,7 @@ namespace osu.Game.Screens.Multi.Lounge if (!IsCurrentScreen) return; - Push(new MatchScreen(room, s => pushGameplayScreen?.Invoke(s))); + Push(new MatchSubScreen(room, s => pushGameplayScreen?.Invoke(s))); } protected override void Dispose(bool isDisposing) @@ -145,7 +146,7 @@ namespace osu.Game.Screens.Multi.Lounge base.Dispose(isDisposing); if (roomManager != null) - roomManager.OpenRequested -= Open; + roomManager.RoomJoined -= Open; } } } diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs similarity index 95% rename from osu.Game/Screens/Multi/Match/MatchScreen.cs rename to osu.Game/Screens/Multi/Match/MatchSubScreen.cs index c784a27b99..982f54f7c8 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -20,7 +20,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Screens.Multi.Match { - public class MatchScreen : MultiplayerScreen + public class MatchSubScreen : MultiplayerSubScreen { public override bool AllowBeatmapRulesetChange => false; public override string Title => room.RoomID.Value == null ? "New room" : room.Name.Value; @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Multi.Match [Resolved(CanBeNull = true)] private IRoomManager manager { get; set; } - public MatchScreen(Room room, Action pushGameplayScreen) + public MatchSubScreen(Room room, Action pushGameplayScreen) { this.room = room; this.pushGameplayScreen = pushGameplayScreen; @@ -119,6 +119,12 @@ namespace osu.Game.Screens.Multi.Match chat.Exit += Exit; } + protected override bool OnExiting(Screen next) + { + manager?.PartRoom(); + return base.OnExiting(next); + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index b9b86fbfc7..b105024a24 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Multi public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; private readonly OsuButton createButton; - private readonly LoungeScreen loungeScreen; + private readonly LoungeSubScreen loungeSubScreen; private OsuScreen currentScreen; @@ -71,9 +71,9 @@ namespace osu.Game.Screens.Multi { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = loungeScreen = new LoungeScreen(Push), + Child = loungeSubScreen = new LoungeSubScreen(Push), }, - new Header(loungeScreen), + new Header(loungeSubScreen), createButton = new HeaderButton { Anchor = Anchor.TopRight, @@ -86,19 +86,22 @@ namespace osu.Game.Screens.Multi Right = 10, }, Text = "Create room", - Action = () => loungeScreen.Open(new Room + Action = () => loungeSubScreen.Open(new Room { Name = { Value = $"{api.LocalUser}'s awesome room" } }), }, roomManager = new RoomManager() }); - screenAdded(loungeScreen); - loungeScreen.Exited += s => Exit(); + + screenAdded(loungeSubScreen); + loungeSubScreen.Exited += _ => Exit(); } protected override void OnEntering(Screen last) { + Content.FadeIn(); + base.OnEntering(last); waves.Show(); } @@ -107,12 +110,13 @@ namespace osu.Game.Screens.Multi { waves.Hide(); + Content.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); + var track = Beatmap.Value.Track; if (track != null) track.Looping = false; - loungeScreen.MakeCurrent(); - loungeScreen.Exit(); + loungeSubScreen.MakeCurrent(); return base.OnExiting(next); } @@ -144,7 +148,7 @@ namespace osu.Game.Screens.Multi { base.Update(); - if (currentScreen is MatchScreen) + if (currentScreen is MatchSubScreen) { var track = Beatmap.Value.Track; if (track != null) @@ -161,7 +165,7 @@ namespace osu.Game.Screens.Multi createButton.Hide(); } - else if (currentScreen is LoungeScreen) + else if (currentScreen is LoungeSubScreen) createButton.Show(); } @@ -175,7 +179,7 @@ namespace osu.Game.Screens.Multi private void screenRemoved(Screen newScreen) { - if (currentScreen is MatchScreen) + if (currentScreen is MatchSubScreen) { var track = Beatmap.Value.Track; if (track != null) diff --git a/osu.Game/Screens/Multi/MultiplayerScreen.cs b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs similarity index 95% rename from osu.Game/Screens/Multi/MultiplayerScreen.cs rename to osu.Game/Screens/Multi/MultiplayerSubScreen.cs index da9a2b3051..5a7eaafba5 100644 --- a/osu.Game/Screens/Multi/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Multi { - public abstract class MultiplayerScreen : OsuScreen, IMultiplayerScreen + public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen { protected virtual Drawable TransitionContent => Content; diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index f33159f69b..0a7c11ecc5 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -72,6 +72,6 @@ namespace osu.Game.Screens.Multi.Play return score; } - protected override Results CreateResults(ScoreInfo score) => new MultiResults(score, room); + protected override Results CreateResults(ScoreInfo score) => new MatchResults(score, room); } } diff --git a/osu.Game/Screens/Multi/Ranking/MultiResults.cs b/osu.Game/Screens/Multi/Ranking/MatchResults.cs similarity index 89% rename from osu.Game/Screens/Multi/Ranking/MultiResults.cs rename to osu.Game/Screens/Multi/Ranking/MatchResults.cs index 0fffe250bf..c0544540c4 100644 --- a/osu.Game/Screens/Multi/Ranking/MultiResults.cs +++ b/osu.Game/Screens/Multi/Ranking/MatchResults.cs @@ -10,11 +10,11 @@ using osu.Game.Screens.Ranking.Types; namespace osu.Game.Screens.Multi.Ranking { - public class MultiResults : Results + public class MatchResults : Results { private readonly Room room; - public MultiResults(ScoreInfo score, Room room) + public MatchResults(ScoreInfo score, Room room) : base(score) { this.room = room; diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 4bd9307bfb..68a11c0ba8 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Multi { public class RoomManager : PollingComponent, IRoomManager { - public event Action OpenRequested; + public event Action RoomJoined; private readonly BindableCollection rooms = new BindableCollection(); public IBindableCollection Rooms => rooms; @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Multi currentJoinRoomRequest.Success += () => { currentRoom = room; - OpenRequested?.Invoke(room); + RoomJoined?.Invoke(room); }; currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}"); diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index f5ce34ea25..5763b84e89 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.Multi; namespace osu.Game.Screens.Select { - public class MatchSongSelect : SongSelect, IMultiplayerScreen + public class MatchSongSelect : SongSelect, IMultiplayerSubScreen { public Action Selected; From 692f5c289d363b0d1fa227675b634f24fb55fbdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:12:51 +0900 Subject: [PATCH 288/355] Move PartRoom calls --- osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs | 9 --------- osu.Game/Screens/Multi/RoomManager.cs | 6 ++++++ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index c49cfc6b9c..7ec04087de 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -106,20 +106,11 @@ namespace osu.Game.Screens.Multi.Lounge protected override bool OnExiting(Screen next) { - roomManager?.PartRoom(); - Filter.Search.HoldFocus = false; // no base call; don't animate return false; } - protected override void OnResuming(Screen last) - { - roomManager?.PartRoom(); - - base.OnResuming(last); - } - protected override void OnSuspending(Screen next) { base.OnSuspending(next); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 68a11c0ba8..0af96c2e1b 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -42,6 +42,12 @@ namespace osu.Game.Screens.Multi TimeBetweenPolls = 5000; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + PartRoom(); + } + public void CreateRoom(Room room) { room.Host.Value = api.LocalUser; From 869081ce9cbe99c5c89c842009ac8de6b88252b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:21:30 +0900 Subject: [PATCH 289/355] Open -> Push --- osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs | 9 ++++++--- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 7ec04087de..aef8265130 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Multi.Lounge private void load() { if (roomManager != null) - roomManager.RoomJoined += Open; + roomManager.RoomJoined += Push; } protected override void UpdateAfterChildren() @@ -123,7 +123,10 @@ namespace osu.Game.Screens.Multi.Lounge roomManager?.Filter(Filter.CreateCriteria()); } - public void Open(Room room) + /// + /// Push a room as a new subscreen. + /// + public void Push(Room room) { // Handles the case where a room is clicked 3 times in quick succession if (!IsCurrentScreen) @@ -137,7 +140,7 @@ namespace osu.Game.Screens.Multi.Lounge base.Dispose(isDisposing); if (roomManager != null) - roomManager.RoomJoined -= Open; + roomManager.RoomJoined -= Push; } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index b105024a24..40f66811f7 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi Right = 10, }, Text = "Create room", - Action = () => loungeSubScreen.Open(new Room + Action = () => loungeSubScreen.Push(new Room { Name = { Value = $"{api.LocalUser}'s awesome room" } }), From 7a431ed87f322320eacda6fc73023ea223701fe8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:31:04 +0900 Subject: [PATCH 290/355] Update ParticipantInfo --- .../Lounge/Components/ParticipantInfo.cs | 47 ++++--------------- .../Multi/Lounge/Components/RoomInspector.cs | 2 +- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index b0ce800d4b..1bc6d5aec0 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -2,12 +2,10 @@ // 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.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -19,12 +17,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class ParticipantInfo : Container { - private readonly FillFlowContainer levelRangeContainer; + private readonly FillFlowContainer summaryContainer; public readonly IBindable Host = new Bindable(); public readonly IBindable> Participants = new Bindable>(); - public ParticipantInfo(string rankPrefix = null) + public ParticipantInfo() { RelativeSizeAxes = Axes.X; Height = 15f; @@ -49,7 +47,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Width = 22f, RelativeSizeAxes = Axes.Y, }, - new Container //todo: team banners + /*new Container //todo: team banners { Width = 38f, RelativeSizeAxes = Axes.Y, @@ -63,7 +61,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Colour = OsuColour.FromHex(@"ad387e"), }, }, - }, + },*/ hostText = new LinkFlowContainer { Anchor = Anchor.CentreLeft, @@ -72,7 +70,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components } }, }, - levelRangeContainer = new FillFlowContainer + summaryContainer = new FillFlowContainer { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -82,34 +80,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components { new OsuSpriteText { - Text = rankPrefix, + Text = "0 participants", TextSize = 14, - }, - new OsuSpriteText - { - Text = "#", - TextSize = 14, - }, - levelRangeLower = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, - new OsuSpriteText - { - Text = " - ", - TextSize = 14, - }, - new OsuSpriteText - { - Text = "#", - TextSize = 14, - }, - levelRangeHigher = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, + } }, }, }; @@ -123,18 +96,18 @@ namespace osu.Game.Screens.Multi.Lounge.Components flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; }); - Participants.BindValueChanged(v => + /*Participants.BindValueChanged(v => { var ranks = v.Select(u => u.Statistics.Ranks.Global); levelRangeLower.Text = ranks.Min().ToString(); levelRangeHigher.Text = ranks.Max().ToString(); - }); + });*/ } [BackgroundDependencyLoader] private void load(OsuColour colours) { - levelRangeContainer.Colour = colours.Gray9; + summaryContainer.Colour = colours.Gray9; } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 08beace4ca..be16d89255 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Padding = contentPadding, Children = new Drawable[] { - participantInfo = new ParticipantInfo(@"Rank Range "), + participantInfo = new ParticipantInfo(), }, }, }, From 052ab4763acf49971326cc47ef6e0062bd0b6896 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 17:44:36 +0900 Subject: [PATCH 291/355] Display room join errors as notifications --- osu.Game/Screens/Multi/RoomManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 68a11c0ba8..2aefc4f558 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Multi RoomJoined?.Invoke(room); }; - currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}"); + currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); api.Queue(currentJoinRoomRequest); } From be9ba78d47a014532b1fba6e97ae3e11dc1164c0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 18:38:58 +0900 Subject: [PATCH 292/355] Add error message when creation fails --- .../Visual/TestCaseLoungeRoomsContainer.cs | 2 +- .../Visual/TestCaseMatchSettingsOverlay.cs | 49 +++++++++++++++++-- .../Online/API/Requests/CreateRoomRequest.cs | 3 +- .../API/Requests/Responses/APICreatedRoom.cs | 14 ++++++ osu.Game/Screens/Multi/IRoomManager.cs | 3 +- .../Match/Components/MatchSettingsOverlay.cs | 44 ++++++++++++++--- osu.Game/Screens/Multi/RoomManager.cs | 10 +++- 7 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index dd7e8f7fac..e42781849d 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual public readonly BindableCollection Rooms = new BindableCollection(); IBindableCollection IRoomManager.Rooms => Rooms; - public void CreateRoom(Room room) => Rooms.Add(room); + public void CreateRoom(Room room, Action onError = null) => Rooms.Add(room); public void JoinRoom(Room room) => RoomJoined?.Invoke(room); diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index 3c41fd6920..a31b91cc2a 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi; @@ -77,7 +78,11 @@ namespace osu.Game.Tests.Visual settings.NameField.Current.Value = expected_name; settings.DurationField.Current.Value = expectedDuration; - roomManager.CreateRequested = r => createdRoom = r; + roomManager.CreateRequested = r => + { + createdRoom = r; + return true; + }; }); AddStep("create room", () => settings.ApplyButton.Action.Invoke()); @@ -85,13 +90,40 @@ namespace osu.Game.Tests.Visual AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration); } - private class TestRoomSettings : MatchSettingsOverlay + [Test] + public void TestCreationFailureDisplaysError() + { + bool fail; + + AddStep("setup", () => + { + fail = true; + roomManager.CreateRequested = _ => !fail; + }); + AddAssert("error not displayed", () => !settings.ErrorText.IsPresent); + + AddStep("create room", () => settings.ApplyButton.Action.Invoke()); + AddAssert("error displayed", () => settings.ErrorText.IsPresent); + AddAssert("error has correct text", () => settings.ErrorText.Text == TestRoomManager.FAILED_TEXT); + + AddStep("create room no fail", () => + { + fail = false; + settings.ApplyButton.Action.Invoke(); + }); + + AddUntilStep(() => !settings.ErrorText.IsPresent, "error not displayed"); + } + + private class TestRoomSettings : RoomSettingsOverlay { public new TriangleButton ApplyButton => base.ApplyButton; public new OsuTextBox NameField => base.NameField; public new OsuDropdown DurationField => base.DurationField; + public new OsuSpriteText ErrorText => base.ErrorText; + public TestRoomSettings(Room room) : base(room) { @@ -100,13 +132,22 @@ namespace osu.Game.Tests.Visual private class TestRoomManager : IRoomManager { - public Action CreateRequested; + public const string FAILED_TEXT = "failed"; + + public Func CreateRequested; public event Action RoomJoined; public IBindableCollection Rooms { get; } = null; - public void CreateRoom(Room room) => CreateRequested?.Invoke(room); + public void CreateRoom(Room room, Action onError = null) + { + if (CreateRequested == null) + return; + + if (!CreateRequested.Invoke(room)) + onError?.Invoke(FAILED_TEXT); + } public void JoinRoom(Room room) => throw new NotImplementedException(); diff --git a/osu.Game/Online/API/Requests/CreateRoomRequest.cs b/osu.Game/Online/API/Requests/CreateRoomRequest.cs index 7ce289b65a..fc401be5f1 100644 --- a/osu.Game/Online/API/Requests/CreateRoomRequest.cs +++ b/osu.Game/Online/API/Requests/CreateRoomRequest.cs @@ -4,11 +4,12 @@ using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; namespace osu.Game.Online.API.Requests { - public class CreateRoomRequest : APIRequest + public class CreateRoomRequest : APIRequest { private readonly Room room; diff --git a/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs b/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs new file mode 100644 index 0000000000..ca0daa04b6 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs @@ -0,0 +1,14 @@ +// 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.Online.Multiplayer; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APICreatedRoom : Room + { + [JsonProperty("error")] + public string Error { get; set; } + } +} diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index b94df93581..bb996f0b5c 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -24,7 +24,8 @@ namespace osu.Game.Screens.Multi /// Creates a new . /// /// The to create. - void CreateRoom(Room room); + /// An action to be invoked if an error occurred. + void CreateRoom(Room room, Action onError = null); /// /// Joins a . diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 6de2bed938..d6228b106b 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.Multi.Match.Components protected readonly TriangleButton ApplyButton; protected readonly OsuPasswordTextBox PasswordField; + protected readonly OsuSpriteText ErrorText; + private readonly Room room; [Resolved(CanBeNull = true)] @@ -200,14 +202,31 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), }, - ApplyButton = new CreateRoomButton + new FillFlowContainer { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), Margin = new MarginPadding { Vertical = 20 }, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(230, 55), - Action = apply, - }, + Children = new Drawable[] + { + ApplyButton = new CreateRoomButton + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(230, 55), + Action = apply, + }, + ErrorText = new OsuSpriteText + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Alpha = 0, + Depth = 1 + } + } + } } } } @@ -229,6 +248,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void load(OsuColour colours) { typeLabel.Colour = colours.Yellow; + ErrorText.Colour = colours.RedDark; MaxParticipantsField.ReadOnly = true; PasswordField.ReadOnly = true; @@ -258,6 +278,8 @@ namespace osu.Game.Screens.Multi.Match.Components private void apply() { + hideError(); + bindings.Name.Value = NameField.Text; bindings.Availability.Value = AvailabilityPicker.Current.Value; bindings.Type.Value = TypePicker.Current.Value; @@ -269,7 +291,15 @@ namespace osu.Game.Screens.Multi.Match.Components bindings.Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(room); + manager?.CreateRoom(room, showError); + } + + private void hideError() => ErrorText.FadeOut(50); + + private void showError(string text) + { + ErrorText.Text = text; + ErrorText.FadeIn(50); } private class SettingsTextBox : OsuTextBox diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 2aefc4f558..c5345e5453 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -42,13 +42,19 @@ namespace osu.Game.Screens.Multi TimeBetweenPolls = 5000; } - public void CreateRoom(Room room) + public void CreateRoom(Room room, Action onError = null) { room.Host.Value = api.LocalUser; var req = new CreateRoomRequest(room); req.Success += result => addRoom(room, result); - req.Failure += exception => Logger.Log($"Failed to create room: {exception}"); + req.Failure += exception => + { + if (req.Result != null) + onError?.Invoke(req.Result.Error); + else + Logger.Log($"Failed to create the room: {exception}", level: LogLevel.Important); + }; api.Queue(req); } From 9d305ba0247bb2444ad74878d5b9eb8574a37e91 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 20:32:01 +0900 Subject: [PATCH 293/355] Reduce code duplication --- osu.Game/Screens/Multi/RoomManager.cs | 45 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index c5345e5453..54d35db1c7 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -47,7 +47,12 @@ namespace osu.Game.Screens.Multi room.Host.Value = api.LocalUser; var req = new CreateRoomRequest(room); - req.Success += result => addRoom(room, result); + req.Success += result => + { + update(room, result); + addRoom(room); + }; + req.Failure += exception => { if (req.Result != null) @@ -114,13 +119,8 @@ namespace osu.Game.Screens.Multi // Add new matches, or update existing foreach (var r in result) { - processPlaylist(r); - - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == r.RoomID.Value); - if (existing == null) - rooms.Add(r); - else - existing.CopyFrom(r); + update(r, r); + addRoom(r); } tcs.SetResult(true); @@ -133,22 +133,29 @@ namespace osu.Game.Screens.Multi return tcs.Task; } - private void addRoom(Room local, Room remote) + /// + /// Updates a local with a remote copy. + /// + /// The local to update. + /// The remote to update with. + private void update(Room local, Room remote) { - processPlaylist(remote); - + foreach (var pi in remote.Playlist) + pi.MapObjects(beatmaps, rulesets); local.CopyFrom(remote); - - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == local.RoomID.Value); - if (existing != null) - rooms.Remove(existing); - rooms.Add(local); } - private void processPlaylist(Room room) + /// + /// Adds a to the list of available rooms. + /// + /// The to add.< + private void addRoom(Room room) { - foreach (var pi in room.Playlist) - pi.MapObjects(beatmaps, rulesets); + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); + if (existing == null) + rooms.Add(room); + else + existing.CopyFrom(room); } } } From 23d412e3ff7720f6a8cc38dddfe6a6db4734bbbd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 20:33:49 +0900 Subject: [PATCH 294/355] Fix post-rebase errors --- osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index a31b91cc2a..f93d1b3069 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual AddUntilStep(() => !settings.ErrorText.IsPresent, "error not displayed"); } - private class TestRoomSettings : RoomSettingsOverlay + private class TestRoomSettings : MatchSettingsOverlay { public new TriangleButton ApplyButton => base.ApplyButton; From 6f0d13e36b240db366cb4d6d4b454e79519250ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:12:51 +0900 Subject: [PATCH 295/355] Move PartRoom calls --- osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs | 9 --------- osu.Game/Screens/Multi/RoomManager.cs | 6 ++++++ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index c49cfc6b9c..7ec04087de 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -106,20 +106,11 @@ namespace osu.Game.Screens.Multi.Lounge protected override bool OnExiting(Screen next) { - roomManager?.PartRoom(); - Filter.Search.HoldFocus = false; // no base call; don't animate return false; } - protected override void OnResuming(Screen last) - { - roomManager?.PartRoom(); - - base.OnResuming(last); - } - protected override void OnSuspending(Screen next) { base.OnSuspending(next); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 54d35db1c7..d91c05f79f 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -42,6 +42,12 @@ namespace osu.Game.Screens.Multi TimeBetweenPolls = 5000; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + PartRoom(); + } + public void CreateRoom(Room room, Action onError = null) { room.Host.Value = api.LocalUser; From 5bd3ab51ddd55755019760437c6baea5ae918cab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:21:30 +0900 Subject: [PATCH 296/355] Open -> Push --- osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs | 9 ++++++--- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 7ec04087de..aef8265130 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Multi.Lounge private void load() { if (roomManager != null) - roomManager.RoomJoined += Open; + roomManager.RoomJoined += Push; } protected override void UpdateAfterChildren() @@ -123,7 +123,10 @@ namespace osu.Game.Screens.Multi.Lounge roomManager?.Filter(Filter.CreateCriteria()); } - public void Open(Room room) + /// + /// Push a room as a new subscreen. + /// + public void Push(Room room) { // Handles the case where a room is clicked 3 times in quick succession if (!IsCurrentScreen) @@ -137,7 +140,7 @@ namespace osu.Game.Screens.Multi.Lounge base.Dispose(isDisposing); if (roomManager != null) - roomManager.RoomJoined -= Open; + roomManager.RoomJoined -= Push; } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index b105024a24..40f66811f7 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Multi Right = 10, }, Text = "Create room", - Action = () => loungeSubScreen.Open(new Room + Action = () => loungeSubScreen.Push(new Room { Name = { Value = $"{api.LocalUser}'s awesome room" } }), From 8386e206c3347ac893e9b0f05f16ff4b0ee350f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:31:04 +0900 Subject: [PATCH 297/355] Update ParticipantInfo --- .../Lounge/Components/ParticipantInfo.cs | 47 ++++--------------- .../Multi/Lounge/Components/RoomInspector.cs | 2 +- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index b0ce800d4b..1bc6d5aec0 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -2,12 +2,10 @@ // 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.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -19,12 +17,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class ParticipantInfo : Container { - private readonly FillFlowContainer levelRangeContainer; + private readonly FillFlowContainer summaryContainer; public readonly IBindable Host = new Bindable(); public readonly IBindable> Participants = new Bindable>(); - public ParticipantInfo(string rankPrefix = null) + public ParticipantInfo() { RelativeSizeAxes = Axes.X; Height = 15f; @@ -49,7 +47,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Width = 22f, RelativeSizeAxes = Axes.Y, }, - new Container //todo: team banners + /*new Container //todo: team banners { Width = 38f, RelativeSizeAxes = Axes.Y, @@ -63,7 +61,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Colour = OsuColour.FromHex(@"ad387e"), }, }, - }, + },*/ hostText = new LinkFlowContainer { Anchor = Anchor.CentreLeft, @@ -72,7 +70,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components } }, }, - levelRangeContainer = new FillFlowContainer + summaryContainer = new FillFlowContainer { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, @@ -82,34 +80,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components { new OsuSpriteText { - Text = rankPrefix, + Text = "0 participants", TextSize = 14, - }, - new OsuSpriteText - { - Text = "#", - TextSize = 14, - }, - levelRangeLower = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, - new OsuSpriteText - { - Text = " - ", - TextSize = 14, - }, - new OsuSpriteText - { - Text = "#", - TextSize = 14, - }, - levelRangeHigher = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, + } }, }, }; @@ -123,18 +96,18 @@ namespace osu.Game.Screens.Multi.Lounge.Components flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; }); - Participants.BindValueChanged(v => + /*Participants.BindValueChanged(v => { var ranks = v.Select(u => u.Statistics.Ranks.Global); levelRangeLower.Text = ranks.Min().ToString(); levelRangeHigher.Text = ranks.Max().ToString(); - }); + });*/ } [BackgroundDependencyLoader] private void load(OsuColour colours) { - levelRangeContainer.Colour = colours.Gray9; + summaryContainer.Colour = colours.Gray9; } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 08beace4ca..be16d89255 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Padding = contentPadding, Children = new Drawable[] { - participantInfo = new ParticipantInfo(@"Rank Range "), + participantInfo = new ParticipantInfo(), }, }, }, From ae47eb61caf9ef810cd0d2d56f12164d78f45c05 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 20:42:47 +0900 Subject: [PATCH 298/355] Fix test not working when not logged in --- .../TestCaseUpdateableBeatmapBackgroundSprite.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs index 24701fccbc..bc449f645b 100644 --- a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -40,12 +40,18 @@ namespace osu.Game.Tests.Visual AddStep("imported", () => beatmapBindable.Value = imported.Beatmaps.First()); if (api.IsLoggedIn) + { AddUntilStep(() => req.Result != null, "wait for api response"); - AddStep("online", () => beatmapBindable.Value = new BeatmapInfo + AddStep("online", () => beatmapBindable.Value = new BeatmapInfo + { + BeatmapSet = req.Result?.ToBeatmapSet(rulesets) + }); + } + else { - BeatmapSet = req.Result?.ToBeatmapSet(rulesets) - }); + AddStep("online (login first)", () => { }); + } } } } From bee4e8ad28bd903a60667abc1ddd4b133a4cd110 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 21:11:31 +0900 Subject: [PATCH 299/355] Fix cancelled webrequests triggering exceptions --- osu.Game/Online/API/APIRequest.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 41f774e83c..ae39d76384 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -92,7 +92,11 @@ namespace osu.Game.Online.API public void Fail(Exception e) { - if (cancelled) return; + if (WebRequest?.Completed == true) + return; + + if (cancelled) + return; cancelled = true; WebRequest?.Abort(); From 9901b116000ecbc16c06498198edd229a1586d72 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 17:44:36 +0900 Subject: [PATCH 300/355] Display room join errors as notifications --- osu.Game/Screens/Multi/RoomManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 0af96c2e1b..1947909438 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Multi RoomJoined?.Invoke(room); }; - currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}"); + currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); api.Queue(currentJoinRoomRequest); } From 940d4a16bbbdedfc616f0a33e45e4e3d792d2100 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 18:38:58 +0900 Subject: [PATCH 301/355] Add error message when creation fails --- .../Visual/TestCaseLoungeRoomsContainer.cs | 2 +- .../Visual/TestCaseMatchSettingsOverlay.cs | 49 +++++++++++++++++-- .../Online/API/Requests/CreateRoomRequest.cs | 3 +- .../API/Requests/Responses/APICreatedRoom.cs | 14 ++++++ osu.Game/Screens/Multi/IRoomManager.cs | 3 +- .../Match/Components/MatchSettingsOverlay.cs | 44 ++++++++++++++--- osu.Game/Screens/Multi/RoomManager.cs | 10 +++- 7 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index dd7e8f7fac..e42781849d 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual public readonly BindableCollection Rooms = new BindableCollection(); IBindableCollection IRoomManager.Rooms => Rooms; - public void CreateRoom(Room room) => Rooms.Add(room); + public void CreateRoom(Room room, Action onError = null) => Rooms.Add(room); public void JoinRoom(Room room) => RoomJoined?.Invoke(room); diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index 3c41fd6920..a31b91cc2a 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi; @@ -77,7 +78,11 @@ namespace osu.Game.Tests.Visual settings.NameField.Current.Value = expected_name; settings.DurationField.Current.Value = expectedDuration; - roomManager.CreateRequested = r => createdRoom = r; + roomManager.CreateRequested = r => + { + createdRoom = r; + return true; + }; }); AddStep("create room", () => settings.ApplyButton.Action.Invoke()); @@ -85,13 +90,40 @@ namespace osu.Game.Tests.Visual AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration); } - private class TestRoomSettings : MatchSettingsOverlay + [Test] + public void TestCreationFailureDisplaysError() + { + bool fail; + + AddStep("setup", () => + { + fail = true; + roomManager.CreateRequested = _ => !fail; + }); + AddAssert("error not displayed", () => !settings.ErrorText.IsPresent); + + AddStep("create room", () => settings.ApplyButton.Action.Invoke()); + AddAssert("error displayed", () => settings.ErrorText.IsPresent); + AddAssert("error has correct text", () => settings.ErrorText.Text == TestRoomManager.FAILED_TEXT); + + AddStep("create room no fail", () => + { + fail = false; + settings.ApplyButton.Action.Invoke(); + }); + + AddUntilStep(() => !settings.ErrorText.IsPresent, "error not displayed"); + } + + private class TestRoomSettings : RoomSettingsOverlay { public new TriangleButton ApplyButton => base.ApplyButton; public new OsuTextBox NameField => base.NameField; public new OsuDropdown DurationField => base.DurationField; + public new OsuSpriteText ErrorText => base.ErrorText; + public TestRoomSettings(Room room) : base(room) { @@ -100,13 +132,22 @@ namespace osu.Game.Tests.Visual private class TestRoomManager : IRoomManager { - public Action CreateRequested; + public const string FAILED_TEXT = "failed"; + + public Func CreateRequested; public event Action RoomJoined; public IBindableCollection Rooms { get; } = null; - public void CreateRoom(Room room) => CreateRequested?.Invoke(room); + public void CreateRoom(Room room, Action onError = null) + { + if (CreateRequested == null) + return; + + if (!CreateRequested.Invoke(room)) + onError?.Invoke(FAILED_TEXT); + } public void JoinRoom(Room room) => throw new NotImplementedException(); diff --git a/osu.Game/Online/API/Requests/CreateRoomRequest.cs b/osu.Game/Online/API/Requests/CreateRoomRequest.cs index 7ce289b65a..fc401be5f1 100644 --- a/osu.Game/Online/API/Requests/CreateRoomRequest.cs +++ b/osu.Game/Online/API/Requests/CreateRoomRequest.cs @@ -4,11 +4,12 @@ using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; namespace osu.Game.Online.API.Requests { - public class CreateRoomRequest : APIRequest + public class CreateRoomRequest : APIRequest { private readonly Room room; diff --git a/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs b/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs new file mode 100644 index 0000000000..ca0daa04b6 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs @@ -0,0 +1,14 @@ +// 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.Online.Multiplayer; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APICreatedRoom : Room + { + [JsonProperty("error")] + public string Error { get; set; } + } +} diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index b94df93581..bb996f0b5c 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -24,7 +24,8 @@ namespace osu.Game.Screens.Multi /// Creates a new . /// /// The to create. - void CreateRoom(Room room); + /// An action to be invoked if an error occurred. + void CreateRoom(Room room, Action onError = null); /// /// Joins a . diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 6de2bed938..d6228b106b 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.Multi.Match.Components protected readonly TriangleButton ApplyButton; protected readonly OsuPasswordTextBox PasswordField; + protected readonly OsuSpriteText ErrorText; + private readonly Room room; [Resolved(CanBeNull = true)] @@ -200,14 +202,31 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), }, - ApplyButton = new CreateRoomButton + new FillFlowContainer { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), Margin = new MarginPadding { Vertical = 20 }, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(230, 55), - Action = apply, - }, + Children = new Drawable[] + { + ApplyButton = new CreateRoomButton + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(230, 55), + Action = apply, + }, + ErrorText = new OsuSpriteText + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Alpha = 0, + Depth = 1 + } + } + } } } } @@ -229,6 +248,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void load(OsuColour colours) { typeLabel.Colour = colours.Yellow; + ErrorText.Colour = colours.RedDark; MaxParticipantsField.ReadOnly = true; PasswordField.ReadOnly = true; @@ -258,6 +278,8 @@ namespace osu.Game.Screens.Multi.Match.Components private void apply() { + hideError(); + bindings.Name.Value = NameField.Text; bindings.Availability.Value = AvailabilityPicker.Current.Value; bindings.Type.Value = TypePicker.Current.Value; @@ -269,7 +291,15 @@ namespace osu.Game.Screens.Multi.Match.Components bindings.Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(room); + manager?.CreateRoom(room, showError); + } + + private void hideError() => ErrorText.FadeOut(50); + + private void showError(string text) + { + ErrorText.Text = text; + ErrorText.FadeIn(50); } private class SettingsTextBox : OsuTextBox diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 1947909438..08458bf4e9 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -48,13 +48,19 @@ namespace osu.Game.Screens.Multi PartRoom(); } - public void CreateRoom(Room room) + public void CreateRoom(Room room, Action onError = null) { room.Host.Value = api.LocalUser; var req = new CreateRoomRequest(room); req.Success += result => addRoom(room, result); - req.Failure += exception => Logger.Log($"Failed to create room: {exception}"); + req.Failure += exception => + { + if (req.Result != null) + onError?.Invoke(req.Result.Error); + else + Logger.Log($"Failed to create the room: {exception}", level: LogLevel.Important); + }; api.Queue(req); } From 5af29f838480b35ba4c9a5c3dd8af7aadcb55871 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 20:32:01 +0900 Subject: [PATCH 302/355] Reduce code duplication --- osu.Game/Screens/Multi/RoomManager.cs | 45 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 08458bf4e9..d91c05f79f 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -53,7 +53,12 @@ namespace osu.Game.Screens.Multi room.Host.Value = api.LocalUser; var req = new CreateRoomRequest(room); - req.Success += result => addRoom(room, result); + req.Success += result => + { + update(room, result); + addRoom(room); + }; + req.Failure += exception => { if (req.Result != null) @@ -120,13 +125,8 @@ namespace osu.Game.Screens.Multi // Add new matches, or update existing foreach (var r in result) { - processPlaylist(r); - - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == r.RoomID.Value); - if (existing == null) - rooms.Add(r); - else - existing.CopyFrom(r); + update(r, r); + addRoom(r); } tcs.SetResult(true); @@ -139,22 +139,29 @@ namespace osu.Game.Screens.Multi return tcs.Task; } - private void addRoom(Room local, Room remote) + /// + /// Updates a local with a remote copy. + /// + /// The local to update. + /// The remote to update with. + private void update(Room local, Room remote) { - processPlaylist(remote); - + foreach (var pi in remote.Playlist) + pi.MapObjects(beatmaps, rulesets); local.CopyFrom(remote); - - var existing = rooms.FirstOrDefault(e => e.RoomID.Value == local.RoomID.Value); - if (existing != null) - rooms.Remove(existing); - rooms.Add(local); } - private void processPlaylist(Room room) + /// + /// Adds a to the list of available rooms. + /// + /// The to add.< + private void addRoom(Room room) { - foreach (var pi in room.Playlist) - pi.MapObjects(beatmaps, rulesets); + var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); + if (existing == null) + rooms.Add(room); + else + existing.CopyFrom(room); } } } From 2e5cd8b4e3c845b46a9fdb321b1458da36137f09 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 20:33:49 +0900 Subject: [PATCH 303/355] Fix post-rebase errors --- osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index a31b91cc2a..f93d1b3069 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual AddUntilStep(() => !settings.ErrorText.IsPresent, "error not displayed"); } - private class TestRoomSettings : RoomSettingsOverlay + private class TestRoomSettings : MatchSettingsOverlay { public new TriangleButton ApplyButton => base.ApplyButton; From 26834abd33c33caf076bdfbc3be51c75a210997c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 21:18:55 +0900 Subject: [PATCH 304/355] Fade and no schedule --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 2 +- osu.Game/Screens/Multi/Match/Components/Header.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index fd00576d21..93783f757b 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps.Drawables public UpdateableBeatmapBackgroundSprite() { - Beatmap.BindValueChanged(b => Schedule(() => Model = b)); + Beatmap.BindValueChanged(b => Model = b); } protected override Drawable CreateDrawable(BeatmapInfo model) diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 4feca7dccb..4f4d5a1d4e 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -140,7 +140,7 @@ namespace osu.Game.Screens.Multi.Match.Components private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite { - protected override double FadeDuration => 0; + protected override double FadeDuration => 200; } } } From 0c384417f152d52b62f4aff2119a008fa2203f8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 20:45:56 +0900 Subject: [PATCH 305/355] Add processing overlay to room creation process --- .../Visual/TestCaseLoungeRoomsContainer.cs | 2 +- .../Visual/TestCaseMatchSettingsOverlay.cs | 4 +++- osu.Game/Screens/Multi/IRoomManager.cs | 3 ++- .../Match/Components/MatchSettingsOverlay.cs | 17 +++++++++++++---- osu.Game/Screens/Multi/RoomManager.cs | 4 +++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index e42781849d..5ecd09e885 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual public readonly BindableCollection Rooms = new BindableCollection(); IBindableCollection IRoomManager.Rooms => Rooms; - public void CreateRoom(Room room, Action onError = null) => Rooms.Add(room); + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => Rooms.Add(room); public void JoinRoom(Room room) => RoomJoined?.Invoke(room); diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index f93d1b3069..086e6fbefe 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -140,13 +140,15 @@ namespace osu.Game.Tests.Visual public IBindableCollection Rooms { get; } = null; - public void CreateRoom(Room room, Action onError = null) + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { if (CreateRequested == null) return; if (!CreateRequested.Invoke(room)) onError?.Invoke(FAILED_TEXT); + else + onSuccess?.Invoke(); } public void JoinRoom(Room room) => throw new NotImplementedException(); diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index bb996f0b5c..0e051802e3 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -24,8 +24,9 @@ namespace osu.Game.Screens.Multi /// Creates a new . /// /// The to create. + /// An action to be invoked if the creation succeeds. /// An action to be invoked if an error occurred. - void CreateRoom(Room room, Action onError = null); + void CreateRoom(Room room, Action onSuccess = null, Action onError = null); /// /// Joins a . diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index d6228b106b..916a21fb71 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -39,6 +39,8 @@ namespace osu.Game.Screens.Multi.Match.Components protected readonly OsuSpriteText ErrorText; + private readonly ProcessingOverlay processingOverlay; + private readonly Room room; [Resolved(CanBeNull = true)] @@ -231,7 +233,8 @@ namespace osu.Game.Screens.Multi.Match.Components } } } - } + }, + processingOverlay = new ProcessingOverlay { Alpha = 0 } }, }; @@ -264,7 +267,7 @@ namespace osu.Game.Screens.Multi.Match.Components ApplyButton.Enabled.Value = hasValidSettings; } - private bool hasValidSettings => NameField.Text.Length > 0 && bindings.Playlist.Count > 0; + private bool hasValidSettings => bindings.Room.RoomID.Value == null && NameField.Text.Length > 0 && bindings.Playlist.Count > 0; protected override void PopIn() { @@ -291,15 +294,21 @@ namespace osu.Game.Screens.Multi.Match.Components bindings.Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(room, showError); + manager?.CreateRoom(room, onSuccess, onError); + + processingOverlay.Show(); } private void hideError() => ErrorText.FadeOut(50); - private void showError(string text) + private void onSuccess() => processingOverlay.Hide(); + + private void onError(string text) { ErrorText.Text = text; ErrorText.FadeIn(50); + + processingOverlay.Hide(); } private class SettingsTextBox : OsuTextBox diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index d91c05f79f..642084547c 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Multi PartRoom(); } - public void CreateRoom(Room room, Action onError = null) + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { room.Host.Value = api.LocalUser; @@ -57,6 +57,8 @@ namespace osu.Game.Screens.Multi { update(room, result); addRoom(room); + + onSuccess?.Invoke(); }; req.Failure += exception => From 152f3b1da3ee2e82216e16c35be3677e5ec7c039 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 21:10:31 +0900 Subject: [PATCH 306/355] Add processing overlay to lounge screen --- .../Visual/TestCaseLoungeRoomsContainer.cs | 8 +-- .../Visual/TestCaseMatchSettingsOverlay.cs | 8 ++- osu.Game/Screens/Multi/IRoomManager.cs | 11 ++-- .../Screens/Multi/Lounge/LoungeSubScreen.cs | 51 ++++++++++--------- .../Match/Components/MatchSettingsOverlay.cs | 2 +- osu.Game/Screens/Multi/RoomManager.cs | 16 +++--- 6 files changed, 49 insertions(+), 47 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index 5ecd09e885..e9dfb0f041 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -71,14 +71,14 @@ namespace osu.Game.Tests.Visual private class TestRoomManager : IRoomManager { - public event Action RoomJoined; - public readonly BindableCollection Rooms = new BindableCollection(); IBindableCollection IRoomManager.Rooms => Rooms; - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => Rooms.Add(room); + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => Rooms.Add(room); - public void JoinRoom(Room room) => RoomJoined?.Invoke(room); + public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) + { + } public void PartRoom() { diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index 086e6fbefe..afce8999b4 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -136,11 +136,9 @@ namespace osu.Game.Tests.Visual public Func CreateRequested; - public event Action RoomJoined; - public IBindableCollection Rooms { get; } = null; - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { if (CreateRequested == null) return; @@ -148,10 +146,10 @@ namespace osu.Game.Tests.Visual if (!CreateRequested.Invoke(room)) onError?.Invoke(FAILED_TEXT); else - onSuccess?.Invoke(); + onSuccess?.Invoke(room); } - public void JoinRoom(Room room) => throw new NotImplementedException(); + public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) => throw new NotImplementedException(); public void PartRoom() => throw new NotImplementedException(); diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index 0e051802e3..a929e1a0f7 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -10,11 +10,6 @@ namespace osu.Game.Screens.Multi { public interface IRoomManager { - /// - /// Invoked when a room is joined. - /// - event Action RoomJoined; - /// /// All the active s. /// @@ -26,13 +21,15 @@ namespace osu.Game.Screens.Multi /// The to create. /// An action to be invoked if the creation succeeds. /// An action to be invoked if an error occurred. - void CreateRoom(Room room, Action onSuccess = null, Action onError = null); + void CreateRoom(Room room, Action onSuccess = null, Action onError = null); /// /// Joins a . /// /// The to join. must be populated. - void JoinRoom(Room room); + /// + /// + void JoinRoom(Room room, Action onSuccess = null, Action onError = null); /// /// Parts the currently-joined . diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index aef8265130..83f91536d3 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Screens; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Lounge.Components; @@ -21,6 +22,7 @@ namespace osu.Game.Screens.Multi.Lounge private readonly Container content; private readonly RoomsContainer rooms; private readonly Action pushGameplayScreen; + private readonly ProcessingOverlay processingOverlay; [Resolved(CanBeNull = true)] private IRoomManager roomManager { get; set; } @@ -43,18 +45,26 @@ namespace osu.Game.Screens.Multi.Lounge RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new ScrollContainer + new Container { RelativeSizeAxes = Axes.Both, Width = 0.55f, - ScrollbarOverlapsContent = false, - Padding = new MarginPadding(10), - Child = new SearchContainer + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = rooms = new RoomsContainer { JoinRequested = r => roomManager?.JoinRoom(r) } - }, + new ScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, + Padding = new MarginPadding(10), + Child = new SearchContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = rooms = new RoomsContainer { JoinRequested = joinRequested } + }, + }, + processingOverlay = new ProcessingOverlay { Alpha = 0 } + } }, inspector = new RoomInspector { @@ -74,13 +84,6 @@ namespace osu.Game.Screens.Multi.Lounge Filter.Search.Exit += Exit; } - [BackgroundDependencyLoader] - private void load() - { - if (roomManager != null) - roomManager.RoomJoined += Push; - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -123,6 +126,16 @@ namespace osu.Game.Screens.Multi.Lounge roomManager?.Filter(Filter.CreateCriteria()); } + private void joinRequested(Room room) + { + processingOverlay.Show(); + roomManager?.JoinRoom(room, r => + { + Open(room); + processingOverlay.Hide(); + }, _ => processingOverlay.Hide()); + } + /// /// Push a room as a new subscreen. /// @@ -134,13 +147,5 @@ namespace osu.Game.Screens.Multi.Lounge Push(new MatchSubScreen(room, s => pushGameplayScreen?.Invoke(s))); } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (roomManager != null) - roomManager.RoomJoined -= Push; - } } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 916a21fb71..1210b9379f 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -301,7 +301,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void hideError() => ErrorText.FadeOut(50); - private void onSuccess() => processingOverlay.Hide(); + private void onSuccess(Room room) => processingOverlay.Hide(); private void onError(string text) { diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 642084547c..6ddfd0fab1 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -19,8 +19,6 @@ namespace osu.Game.Screens.Multi { public class RoomManager : PollingComponent, IRoomManager { - public event Action RoomJoined; - private readonly BindableCollection rooms = new BindableCollection(); public IBindableCollection Rooms => rooms; @@ -48,7 +46,7 @@ namespace osu.Game.Screens.Multi PartRoom(); } - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { room.Host.Value = api.LocalUser; @@ -58,7 +56,7 @@ namespace osu.Game.Screens.Multi update(room, result); addRoom(room); - onSuccess?.Invoke(); + onSuccess?.Invoke(room); }; req.Failure += exception => @@ -74,7 +72,7 @@ namespace osu.Game.Screens.Multi private JoinRoomRequest currentJoinRoomRequest; - public void JoinRoom(Room room) + public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) { currentJoinRoomRequest?.Cancel(); currentJoinRoomRequest = null; @@ -83,10 +81,14 @@ namespace osu.Game.Screens.Multi currentJoinRoomRequest.Success += () => { currentRoom = room; - RoomJoined?.Invoke(room); + onSuccess?.Invoke(room); }; - currentJoinRoomRequest.Failure += exception => Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); + currentJoinRoomRequest.Failure += exception => + { + Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); + onError?.Invoke(exception.ToString()); + }; api.Queue(currentJoinRoomRequest); } From 2d19436456a1fa177fd07339c839a3fac5451b9d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 21:21:26 +0900 Subject: [PATCH 307/355] Open -> Push --- osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 83f91536d3..d9633218eb 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -131,7 +131,7 @@ namespace osu.Game.Screens.Multi.Lounge processingOverlay.Show(); roomManager?.JoinRoom(room, r => { - Open(room); + Push(room); processingOverlay.Hide(); }, _ => processingOverlay.Hide()); } From a1fa914c66fdb41209bcfeb019381296ee5fb07d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 21:58:14 +0900 Subject: [PATCH 308/355] Participants --- osu.Game/Online/Multiplayer/Room.cs | 4 ++++ osu.Game/Screens/Multi/Components/ParticipantCount.cs | 6 ++++-- osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs | 1 + .../Screens/Multi/Lounge/Components/ParticipantInfo.cs | 7 ++++++- osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs | 7 +++++-- osu.Game/Screens/Multi/Match/Components/Participants.cs | 6 ++++-- osu.Game/Screens/Multi/RoomBindings.cs | 3 +++ 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index b17d08320c..d7898297c9 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -49,6 +49,9 @@ namespace osu.Game.Online.Multiplayer [JsonIgnore] public Bindable> Participants { get; private set; } = new Bindable>(Enumerable.Empty()); + [JsonProperty("participant_count")] + public Bindable ParticipantCount { get; private set; } = new Bindable(); + [JsonProperty("duration")] private int duration { @@ -85,6 +88,7 @@ namespace osu.Game.Online.Multiplayer Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; + ParticipantCount.Value = other.ParticipantCount.Value; Participants.Value = other.Participants.Value.ToArray(); EndDate.Value = other.EndDate; diff --git a/osu.Game/Screens/Multi/Components/ParticipantCount.cs b/osu.Game/Screens/Multi/Components/ParticipantCount.cs index 8665678562..fc19039872 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantCount.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantCount.cs @@ -11,7 +11,7 @@ using osu.Game.Users; namespace osu.Game.Screens.Multi.Components { - public class ParticipantCount : CompositeDrawable + public class ParticipantCountDisplay : CompositeDrawable { private const float text_size = 30; private const float transition_duration = 100; @@ -19,9 +19,10 @@ namespace osu.Game.Screens.Multi.Components private readonly OsuSpriteText slash, maxText; public readonly IBindable> Participants = new Bindable>(); + public readonly IBindable ParticipantCount = new Bindable(); public readonly IBindable MaxParticipants = new Bindable(); - public ParticipantCount() + public ParticipantCountDisplay() { AutoSizeAxes = Axes.Both; @@ -55,6 +56,7 @@ namespace osu.Game.Screens.Multi.Components Participants.BindValueChanged(v => count.Text = v.Count().ToString()); MaxParticipants.BindValueChanged(_ => updateMax(), true); + ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0")); } private void updateMax() diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index d62b628389..0540eed1aa 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -217,6 +217,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components modeTypeInfo.Type.BindTo(bindings.Type); participantInfo.Host.BindTo(bindings.Host); participantInfo.Participants.BindTo(bindings.Participants); + participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); bindings.Name.BindValueChanged(n => name.Text = n, true); bindings.EndDate.BindValueChanged(d => endDate.Date = d, true); diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 1bc6d5aec0..34fc7fe886 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -21,9 +22,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components public readonly IBindable Host = new Bindable(); public readonly IBindable> Participants = new Bindable>(); + public readonly IBindable ParticipantCount = new Bindable(); public ParticipantInfo() { + OsuSpriteText summary; RelativeSizeAxes = Axes.X; Height = 15f; @@ -78,7 +81,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Direction = FillDirection.Horizontal, Children = new[] { - new OsuSpriteText + summary = new OsuSpriteText { Text = "0 participants", TextSize = 14, @@ -96,6 +99,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; }); + ParticipantCount.BindValueChanged(v => summary.Text = $"{v:#,0}{" participant".Pluralize(v == 1)}"); + /*Participants.BindValueChanged(v => { var ranks = v.Select(u => u.Statistics.Ranks.Global); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index be16d89255..a7fa592323 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private OsuColour colours; private Box statusStrip; private UpdateableBeatmapBackgroundSprite background; - private ParticipantCount participantCount; + private ParticipantCountDisplay participantCount; private FillFlowContainer topFlow, participantsFlow; private OsuSpriteText name, status; private BeatmapTypeInfo beatmapTypeInfo; @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Padding = new MarginPadding(20), Children = new Drawable[] { - participantCount = new ParticipantCount + participantCount = new ParticipantCountDisplay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -167,9 +167,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components }; participantInfo.Host.BindTo(bindings.Host); + participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); participantInfo.Participants.BindTo(bindings.Participants); + participantCount.Participants.BindTo(bindings.Participants); participantCount.MaxParticipants.BindTo(bindings.MaxParticipants); + beatmapTypeInfo.Type.BindTo(bindings.Type); background.Beatmap.BindTo(bindings.CurrentBeatmap); beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); diff --git a/osu.Game/Screens/Multi/Match/Components/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs index 4f18fc9f4c..56c8c3e8fc 100644 --- a/osu.Game/Screens/Multi/Match/Components/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -16,12 +16,13 @@ namespace osu.Game.Screens.Multi.Match.Components public class Participants : CompositeDrawable { public readonly IBindable> Users = new Bindable>(); + public readonly IBindable ParticipantCount = new Bindable(); public readonly IBindable MaxParticipants = new Bindable(); public Participants() { FillFlowContainer usersFlow; - ParticipantCount count; + ParticipantCountDisplay count; InternalChild = new Container { @@ -35,7 +36,7 @@ namespace osu.Game.Screens.Multi.Match.Components Padding = new MarginPadding { Top = 10 }, Children = new Drawable[] { - count = new ParticipantCount + count = new ParticipantCountDisplay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -55,6 +56,7 @@ namespace osu.Game.Screens.Multi.Match.Components }; count.Participants.BindTo(Users); + count.ParticipantCount.BindTo(ParticipantCount); count.MaxParticipants.BindTo(MaxParticipants); Users.BindValueChanged(v => diff --git a/osu.Game/Screens/Multi/RoomBindings.cs b/osu.Game/Screens/Multi/RoomBindings.cs index e84fa9c261..9a38ba1f60 100644 --- a/osu.Game/Screens/Multi/RoomBindings.cs +++ b/osu.Game/Screens/Multi/RoomBindings.cs @@ -45,6 +45,7 @@ namespace osu.Game.Screens.Multi Type.UnbindFrom(room.Type); Playlist.UnbindFrom(room.Playlist); Participants.UnbindFrom(room.Participants); + ParticipantCount.UnbindFrom(room.ParticipantCount); MaxParticipants.UnbindFrom(room.MaxParticipants); EndDate.UnbindFrom(room.EndDate); Availability.UnbindFrom(room.Availability); @@ -61,6 +62,7 @@ namespace osu.Game.Screens.Multi Type.BindTo(room.Type); Playlist.BindTo(room.Playlist); Participants.BindTo(room.Participants); + ParticipantCount.BindTo(room.ParticipantCount); MaxParticipants.BindTo(room.MaxParticipants); EndDate.BindTo(room.EndDate); Availability.BindTo(room.Availability); @@ -86,6 +88,7 @@ namespace osu.Game.Screens.Multi public readonly Bindable Type = new Bindable(); public readonly BindableCollection Playlist = new BindableCollection(); public readonly Bindable> Participants = new Bindable>(); + public readonly Bindable ParticipantCount = new Bindable(); public readonly Bindable MaxParticipants = new Bindable(); public readonly Bindable EndDate = new Bindable(); public readonly Bindable Availability = new Bindable(); From e7310a16c7b9d3fec811f6a7c7c484445fdabdfc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 26 Dec 2018 22:14:49 +0900 Subject: [PATCH 309/355] Fix playlist not updating correcly --- osu.Game/Online/Multiplayer/PlaylistItem.cs | 2 +- osu.Game/Online/Multiplayer/Room.cs | 2 ++ osu.Game/Screens/Multi/RoomManager.cs | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/PlaylistItem.cs b/osu.Game/Online/Multiplayer/PlaylistItem.cs index e887295f4a..4155121bdf 100644 --- a/osu.Game/Online/Multiplayer/PlaylistItem.cs +++ b/osu.Game/Online/Multiplayer/PlaylistItem.cs @@ -66,7 +66,7 @@ namespace osu.Game.Online.Multiplayer public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) { // If we don't have an api beatmap, the request occurred as a result of room creation, so we can query the local beatmap instead - // Todo: Is this a bug? + // Todo: Is this a bug? Room creation only returns the beatmap ID Beatmap = apiBeatmap == null ? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == BeatmapID) : apiBeatmap.ToBeatmap(rulesets); Ruleset = rulesets.GetRuleset(RulesetID); diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index d7898297c9..924bf75809 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -95,6 +95,8 @@ namespace osu.Game.Online.Multiplayer // Todo: Temporary, should only remove/add new items (requires framework changes) if (Playlist.Count == 0) Playlist.AddRange(other.Playlist); + else if (other.Playlist.Count > 0) + Playlist.First().ID = other.Playlist.First().ID; } public bool ShouldSerializeRoomID() => false; diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index c24ef4664f..552f24df8a 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -154,7 +154,9 @@ namespace osu.Game.Screens.Multi { foreach (var pi in remote.Playlist) pi.MapObjects(beatmaps, rulesets); - local.CopyFrom(remote); + + if (local != remote) + local.CopyFrom(remote); } /// From 8cf30bdb6a8cbb84e48be1e4d931e38499d8ea4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 22:16:35 +0900 Subject: [PATCH 310/355] Play with delegate --- osu.Game.Tests/Visual/TestCasePlayerLoader.cs | 6 ++-- osu.Game/OsuGame.cs | 2 +- .../Screens/Multi/Match/MatchSubScreen.cs | 8 +++-- osu.Game/Screens/Play/PlayerLoader.cs | 35 ++++++++++++------- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/TestCasePlayerLoader.cs index de839a21af..6ec3bd108b 100644 --- a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/TestCasePlayerLoader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual { Beatmap.Value = new DummyWorkingBeatmap(game); - AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(new Player + AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(() => new Player { AllowPause = false, AllowLeadIn = false, @@ -30,9 +30,9 @@ namespace osu.Game.Tests.Visual AddStep("load slow dummy beatmap", () => { - SlowLoadPlayer slow; + SlowLoadPlayer slow = null; - Add(loader = new PlayerLoader(slow = new SlowLoadPlayer + Add(loader = new PlayerLoader(() => slow = new SlowLoadPlayer { AllowPause = false, AllowLeadIn = false, diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 41f2caf40e..6a5f9656d1 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -317,7 +317,7 @@ namespace osu.Game Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); Beatmap.Value.Mods.Value = databasedScoreInfo.Mods; - currentScreen.Push(new PlayerLoader(new ReplayPlayer(databasedScore))); + currentScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); } } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 982f54f7c8..5cd5d9e76a 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -167,10 +167,12 @@ namespace osu.Game.Screens.Multi.Match { default: case GameTypeTimeshift _: - var player = new TimeshiftPlayer(room, room.Playlist.First().ID); - player.Exited += _ => leaderboard.RefreshScores(); + pushGameplayScreen?.Invoke(new PlayerLoader(() => { + var player = new TimeshiftPlayer(room, room.Playlist.First().ID); + player.Exited += _ => leaderboard.RefreshScores(); - pushGameplayScreen?.Invoke(new PlayerLoader(player)); + return player; + })); break; } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index bf44a60473..ded25f013a 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.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; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; @@ -24,6 +25,7 @@ namespace osu.Game.Screens.Play { public class PlayerLoader : ScreenWithBeatmapBackground { + private readonly Func createPlayer; private static readonly Vector2 background_blur = new Vector2(15); private Player player; @@ -35,15 +37,15 @@ namespace osu.Game.Screens.Play private Task loadTask; - public PlayerLoader(Player player) + public PlayerLoader(Func createPlayer) { - this.player = player; + this.createPlayer = createPlayer; + } - player.RestartRequested = () => - { - hideOverlays = true; - ValidForResume = true; - }; + private void restartRequested() + { + hideOverlays = true; + ValidForResume = true; } [BackgroundDependencyLoader] @@ -71,7 +73,7 @@ namespace osu.Game.Screens.Play } }); - loadTask = LoadComponentAsync(player, playerLoaded); + loadNewPlayer(); } private void playerLoaded(Player player) => info.Loading = false; @@ -85,15 +87,22 @@ namespace osu.Game.Screens.Play info.Loading = true; //we will only be resumed if the player has requested a re-run (see ValidForResume setting above) - loadTask = LoadComponentAsync(player = new Player - { - RestartCount = player.RestartCount + 1, - RestartRequested = player.RestartRequested, - }, playerLoaded); + loadNewPlayer(); this.Delay(400).Schedule(pushWhenLoaded); } + private void loadNewPlayer() + { + var restartCount = player?.RestartCount + 1 ?? 0; + + player = createPlayer(); + player.RestartCount = restartCount; + player.RestartRequested = restartRequested; + + loadTask = LoadComponentAsync(player, playerLoaded); + } + private void contentIn() { Content.ScaleTo(1, 650, Easing.OutQuint); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index cbe22d968a..a7de93b11d 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Select SampleConfirm?.Play(); - LoadComponentAsync(player = new PlayerLoader(new Player()), l => + LoadComponentAsync(player = new PlayerLoader(() => new Player()), l => { if (IsCurrentScreen) Push(player); }); From 6b7b0af2e4d22a9ba45554fe02a611f318179bc4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 22:25:15 +0900 Subject: [PATCH 311/355] Temporary fix for participant count being nullable --- osu.Game/Online/Multiplayer/Room.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 924bf75809..c517b5aef5 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -49,9 +49,17 @@ namespace osu.Game.Online.Multiplayer [JsonIgnore] public Bindable> Participants { get; private set; } = new Bindable>(Enumerable.Empty()); - [JsonProperty("participant_count")] + public Bindable ParticipantCount { get; private set; } = new Bindable(); + // todo: TEMPORARY + [JsonProperty("participant_count")] + private int? participantCount + { + get => ParticipantCount; + set => ParticipantCount.Value = value ?? 0; + } + [JsonProperty("duration")] private int duration { From cc1f3d54b017be1193919eb1953c6f11d1ce66f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 22:37:09 +0900 Subject: [PATCH 312/355] Fix looping failure --- osu.Game/Screens/Multi/Multiplayer.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 40f66811f7..499198d800 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -134,9 +134,18 @@ namespace osu.Game.Screens.Multi Content.ScaleTo(1.1f, 250, Easing.InSine); Content.FadeOut(250); + cancelLooping(); + base.OnSuspending(next); } + private void cancelLooping() + { + var track = Beatmap.Value.Track; + if (track != null) + track.Looping = false; + } + protected override void LogoExiting(OsuLogo logo) { // the wave overlay transition takes longer than expected to run. @@ -148,6 +157,8 @@ namespace osu.Game.Screens.Multi { base.Update(); + if (!IsCurrentScreen) return; + if (currentScreen is MatchSubScreen) { var track = Beatmap.Value.Track; @@ -180,11 +191,7 @@ namespace osu.Game.Screens.Multi private void screenRemoved(Screen newScreen) { if (currentScreen is MatchSubScreen) - { - var track = Beatmap.Value.Track; - if (track != null) - track.Looping = false; - } + cancelLooping(); currentScreen = (OsuScreen)newScreen; } From bb502769c72ba0d86832eaaaf7bad7211d782799 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Dec 2018 22:42:17 +0900 Subject: [PATCH 313/355] Fix enum --- osu.Game/Scoring/ScoreInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 8ffade1e2b..b863566967 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Rulesets; @@ -20,6 +21,7 @@ namespace osu.Game.Scoring public int ID { get; set; } [JsonProperty("rank")] + [JsonConverter(typeof(StringEnumConverter))] public ScoreRank Rank { get; set; } [JsonProperty("total_score")] From 1e71c5c9c4959296bd0d936bf2d3b6c840612a18 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 13:30:36 +0900 Subject: [PATCH 314/355] Add + set ended room status --- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 1 + osu.Game.Tests/Visual/TestCaseRoomStatus.cs | 50 +++++++++++++++++++ osu.Game/Online/Multiplayer/Room.cs | 4 ++ osu.Game/Online/Multiplayer/RoomStatus.cs | 12 ----- .../RoomStatuses/RoomStatusEnded.cs | 14 ++++++ .../RoomStatuses/RoomStatusOpen.cs | 14 ++++++ .../RoomStatuses/RoomStatusPlaying.cs | 14 ++++++ osu.Game/Screens/Multi/RoomManager.cs | 3 +- 8 files changed, 98 insertions(+), 14 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseRoomStatus.cs create mode 100644 osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs create mode 100644 osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs create mode 100644 osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index be3367bf6c..4da500427b 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Match.Components; diff --git a/osu.Game.Tests/Visual/TestCaseRoomStatus.cs b/osu.Game.Tests/Visual/TestCaseRoomStatus.cs new file mode 100644 index 0000000000..d44b399a95 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseRoomStatus.cs @@ -0,0 +1,50 @@ +// 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 osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.RoomStatuses; +using osu.Game.Screens.Multi.Lounge.Components; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseRoomStatus : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RoomStatusEnded), + typeof(RoomStatusOpen), + typeof(RoomStatusPlaying) + }; + + public TestCaseRoomStatus() + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Width = 0.5f, + Children = new Drawable[] + { + new DrawableRoom(new Room + { + Name = { Value = "Room 1" }, + Status = { Value = new RoomStatusOpen() } + }), + new DrawableRoom(new Room + { + Name = { Value = "Room 2" }, + Status = { Value = new RoomStatusPlaying() } + }), + new DrawableRoom(new Room + { + Name = { Value = "Room 3" }, + Status = { Value = new RoomStatusEnded() } + }), + } + }; + } + } +} diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index c517b5aef5..80558b14db 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -7,6 +7,7 @@ using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; using osu.Game.Online.Multiplayer.GameTypes; +using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Users; namespace osu.Game.Online.Multiplayer @@ -100,6 +101,9 @@ namespace osu.Game.Online.Multiplayer Participants.Value = other.Participants.Value.ToArray(); EndDate.Value = other.EndDate; + if (DateTimeOffset.Now >= EndDate.Value) + Status.Value = new RoomStatusEnded(); + // Todo: Temporary, should only remove/add new items (requires framework changes) if (Playlist.Count == 0) Playlist.AddRange(other.Playlist); diff --git a/osu.Game/Online/Multiplayer/RoomStatus.cs b/osu.Game/Online/Multiplayer/RoomStatus.cs index 7c6e71a360..e2d84500a9 100644 --- a/osu.Game/Online/Multiplayer/RoomStatus.cs +++ b/osu.Game/Online/Multiplayer/RoomStatus.cs @@ -11,16 +11,4 @@ namespace osu.Game.Online.Multiplayer public abstract string Message { get; } public abstract Color4 GetAppropriateColour(OsuColour colours); } - - public class RoomStatusOpen : RoomStatus - { - public override string Message => @"Welcoming Players"; - public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight; - } - - public class RoomStatusPlaying : RoomStatus - { - public override string Message => @"Now Playing"; - public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple; - } } diff --git a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs new file mode 100644 index 0000000000..e6ab3ab495 --- /dev/null +++ b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Online.Multiplayer.RoomStatuses +{ + public class RoomStatusEnded : RoomStatus + { + public override string Message => @"Ended"; + public override Color4 GetAppropriateColour(OsuColour colours) => colours.YellowDarker; + } +} diff --git a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs new file mode 100644 index 0000000000..6bc701feda --- /dev/null +++ b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Online.Multiplayer.RoomStatuses +{ + public class RoomStatusOpen : RoomStatus + { + public override string Message => @"Welcoming Players"; + public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight; + } +} diff --git a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs new file mode 100644 index 0000000000..a725aca03a --- /dev/null +++ b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Online.Multiplayer.RoomStatuses +{ + public class RoomStatusPlaying : RoomStatus + { + public override string Message => @"Now Playing"; + public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple; + } +} diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 552f24df8a..ceecaf5443 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -155,8 +155,7 @@ namespace osu.Game.Screens.Multi foreach (var pi in remote.Playlist) pi.MapObjects(beatmaps, rulesets); - if (local != remote) - local.CopyFrom(remote); + local.CopyFrom(remote); } /// From 67e200e1b2e5bd98cc744c62897352938e1b8e4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 15:30:02 +0900 Subject: [PATCH 315/355] Leaderboard design updates --- ...ultiResults.cs => TestCaseMatchResults.cs} | 18 +++-- osu.Game.Tests/Visual/TestCaseResults.cs | 2 +- osu.Game/Online/Leaderboards/Leaderboard.cs | 66 +++++++++++-------- .../Online/Leaderboards/LeaderboardScore.cs | 4 +- .../Screens/Multi/Ranking/MatchResults.cs | 2 +- ...gResultsPage.cs => RoomLeaderboardPage.cs} | 59 ++++++++++++++--- .../Ranking/Types/RoomLeaderboardPageInfo.cs | 4 +- osu.Game/Screens/Play/SoloResults.cs | 2 +- ...ResultsPage.cs => LocalLeaderboardPage.cs} | 6 +- ...ageInfo.cs => LocalLeaderboardPageInfo.cs} | 10 +-- .../Select/Leaderboards/BeatmapLeaderboard.cs | 2 + 11 files changed, 118 insertions(+), 57 deletions(-) rename osu.Game.Tests/Visual/{TestCaseMultiResults.cs => TestCaseMatchResults.cs} (85%) rename osu.Game/Screens/Multi/Ranking/Pages/{RoomRankingResultsPage.cs => RoomLeaderboardPage.cs} (61%) rename osu.Game/Screens/Ranking/Pages/{RankingResultsPage.cs => LocalLeaderboardPage.cs} (85%) rename osu.Game/Screens/Ranking/Types/{BeatmapLeaderboardPageInfo.cs => LocalLeaderboardPageInfo.cs} (59%) diff --git a/osu.Game.Tests/Visual/TestCaseMultiResults.cs b/osu.Game.Tests/Visual/TestCaseMatchResults.cs similarity index 85% rename from osu.Game.Tests/Visual/TestCaseMultiResults.cs rename to osu.Game.Tests/Visual/TestCaseMatchResults.cs index 8991782835..086f329608 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiResults.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchResults.cs @@ -19,13 +19,13 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual { - public class TestCaseMultiResults : OsuTestCase + public class TestCaseMatchResults : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(MatchResults), typeof(RoomLeaderboardPageInfo), - typeof(RoomRankingResultsPage) + typeof(RoomLeaderboardPage) }; [Resolved] @@ -49,7 +49,11 @@ namespace osu.Game.Tests.Visual private readonly Room room; public TestMatchResults(ScoreInfo score) - : this(score, new Room()) + : this(score, new Room + { + RoomID = { Value = 1 }, + Name = { Value = "an awesome room" } + }) { } @@ -76,12 +80,12 @@ namespace osu.Game.Tests.Visual this.room = room; } - public override ResultsPage CreatePage() => new TestRoomRankingResultsPage(score, beatmap, room); + public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap, room); } - private class TestRoomRankingResultsPage : RoomRankingResultsPage + private class TestRoomLeaderboardPage : RoomLeaderboardPage { - public TestRoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) + public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) : base(score, beatmap, room) { } @@ -89,7 +93,7 @@ namespace osu.Game.Tests.Visual protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room); } - private class TestMatchLeaderboard : MatchLeaderboard + private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard { public TestMatchLeaderboard(Room room) : base(room) diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/TestCaseResults.cs index a954c6c57c..98aaa23beb 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/TestCaseResults.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual typeof(Results), typeof(ResultsPage), typeof(ScoreResultsPage), - typeof(RankingResultsPage) + typeof(LocalLeaderboardPage) }; [BackgroundDependencyLoader] diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index d9d78245bb..a30a3c4254 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Online.Leaderboards { - public abstract class Leaderboard : Container + public abstract class Leaderboard : Container, IOnlineComponent { private const double fade_duration = 300; @@ -55,14 +55,8 @@ namespace osu.Game.Online.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - var flow = scrollFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0f, 5f), - Padding = new MarginPadding { Top = 10, Bottom = 5 }, - ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)) - }; + scrollFlow = CreateScoreFlow(); + scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); // schedule because we may not be loaded yet (LoadComponentAsync complains). showScoresDelegate?.Cancel(); @@ -71,12 +65,12 @@ namespace osu.Game.Online.Leaderboards else showScores(); - void showScores() => LoadComponentAsync(flow, _ => + void showScores() => LoadComponentAsync(scrollFlow, _ => { - scrollContainer.Add(flow); + scrollContainer.Add(scrollFlow); int i = 0; - foreach (var s in flow.Children) + foreach (var s in scrollFlow.Children) { using (s.BeginDelayedSequence(i++ * 50, true)) s.Show(); @@ -87,6 +81,16 @@ namespace osu.Game.Online.Leaderboards } } + protected virtual FillFlowContainer CreateScoreFlow() + => new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0f, 5f), + Padding = new MarginPadding { Top = 10, Bottom = 5 }, + + }; + private TScope scope; public TScope Scope @@ -175,26 +179,22 @@ namespace osu.Game.Online.Leaderboards private void load(APIAccess api) { this.api = api; - - if (api != null) - api.OnStateChange += handleApiStateChange; + api?.Register(this); } protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - - if (api != null) - api.OnStateChange -= handleApiStateChange; + api?.Unregister(this); } public void RefreshScores() => UpdateScores(); private APIRequest getScoresRequest; - private void handleApiStateChange(APIState oldState, APIState newState) + public void APIStateChanged(APIAccess api, APIState state) { - if (newState == APIState.Online) + if (state == APIState.Online) UpdateScores(); } @@ -265,14 +265,18 @@ namespace osu.Game.Online.Leaderboards currentPlaceholder = placeholder; } + protected virtual bool FadeBottom => true; + protected virtual bool FadeTop => true; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - var fadeStart = scrollContainer.Current + scrollContainer.DrawHeight; + var fadeBottom = scrollContainer.Current + scrollContainer.DrawHeight; + var fadeTop = scrollContainer.Current + LeaderboardScore.HEIGHT; if (!scrollContainer.IsScrolledToEnd()) - fadeStart -= LeaderboardScore.HEIGHT; + fadeBottom -= LeaderboardScore.HEIGHT; if (scrollFlow == null) return; @@ -282,15 +286,23 @@ namespace osu.Game.Online.Leaderboards var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y; var bottomY = topY + LeaderboardScore.HEIGHT; - if (bottomY < fadeStart) + bool requireTopFade = FadeTop && topY <= fadeTop; + bool requireBottomFade = FadeBottom && bottomY >= fadeBottom; + + if (!requireTopFade && !requireBottomFade) c.Colour = Color4.White; - else if (topY > fadeStart + LeaderboardScore.HEIGHT) + else if (topY > fadeBottom + LeaderboardScore.HEIGHT || bottomY < fadeTop - LeaderboardScore.HEIGHT) c.Colour = Color4.Transparent; else { - c.Colour = ColourInfo.GradientVertical( - Color4.White.Opacity(Math.Min(1 - (topY - fadeStart) / LeaderboardScore.HEIGHT, 1)), - Color4.White.Opacity(Math.Min(1 - (bottomY - fadeStart) / LeaderboardScore.HEIGHT, 1))); + if (bottomY - fadeBottom > 0 && FadeBottom) + c.Colour = ColourInfo.GradientVertical( + Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / LeaderboardScore.HEIGHT, 1)), + Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / LeaderboardScore.HEIGHT, 1))); + else if (FadeTop) + c.Colour = ColourInfo.GradientVertical( + Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / LeaderboardScore.HEIGHT, 1)), + Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / LeaderboardScore.HEIGHT, 1))); } } } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 0c64105d5c..e60a73467b 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -73,8 +73,8 @@ namespace osu.Game.Online.Leaderboards { new OsuSpriteText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Font = @"Exo2.0-MediumItalic", TextSize = 22, // ReSharper disable once ImpureMethodCallOnReadonlyValueField diff --git a/osu.Game/Screens/Multi/Ranking/MatchResults.cs b/osu.Game/Screens/Multi/Ranking/MatchResults.cs index c0544540c4..018eb60564 100644 --- a/osu.Game/Screens/Multi/Ranking/MatchResults.cs +++ b/osu.Game/Screens/Multi/Ranking/MatchResults.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Multi.Ranking protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { new ScoreOverviewPageInfo(Score, Beatmap), - new BeatmapLeaderboardPageInfo(Score, Beatmap), + new LocalLeaderboardPageInfo(Score, Beatmap), new RoomLeaderboardPageInfo(Score, Beatmap, room), }; } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs similarity index 61% rename from osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs rename to osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index a3836ed82a..8423a76a36 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomRankingResultsPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -13,6 +13,7 @@ using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Match.Components; @@ -20,7 +21,7 @@ using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Multi.Ranking.Pages { - public class RoomRankingResultsPage : ResultsPage + public class RoomLeaderboardPage : ResultsPage { private readonly Room room; @@ -28,7 +29,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages private TextFlowContainer rankText; - public RoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) + public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) : base(score, beatmap) { this.room = room; @@ -45,13 +46,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { new Box { - Colour = colours.GrayE, + Colour = colours.Gray6, RelativeSizeAxes = Axes.Both, }, new BufferedContainer { RelativeSizeAxes = Axes.Both, - BackgroundColour = colours.GrayE, + BackgroundColour = colours.Gray6, Child = leaderboard = CreateLeaderboard(room) }, rankText = new TextFlowContainer @@ -61,7 +62,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages RelativeSizeAxes = Axes.X, Width = 0.5f, AutoSizeAxes = Axes.Y, - Y = 75, + Y = 50, TextAnchor = Anchor.TopCentre }, }; @@ -70,14 +71,20 @@ namespace osu.Game.Screens.Multi.Ranking.Pages leaderboard.Anchor = Anchor.Centre; leaderboard.RelativeSizeAxes = Axes.Both; leaderboard.Height = 0.8f; - leaderboard.Y = 95; + leaderboard.Y = 55; leaderboard.ScoresLoaded = scoresLoaded; } private void scoresLoaded(IEnumerable scores) { - Action gray = s => s.Colour = colours.Gray8; + Action gray = s => s.Colour = colours.GrayC; + Action white = s => + { + s.TextSize *= 1.4f; + s.Colour = colours.GrayF; + }; + rankText.AddText(room.Name + "\n", white); rankText.AddText("You are placed ", gray); int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); @@ -91,6 +98,42 @@ namespace osu.Game.Screens.Multi.Ranking.Pages rankText.AddText("in the room!", gray); } - protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new MatchLeaderboard(room); + protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new ResultsMatchLeaderboard(room); + + public class ResultsMatchLeaderboard : MatchLeaderboard + { + public ResultsMatchLeaderboard(Room room) + : base(room) + { + } + + protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) + => new ResultsMatchLeaderboardScore(model, index); + + protected override FillFlowContainer CreateScoreFlow() + { + var flow = base.CreateScoreFlow(); + flow.Padding = new MarginPadding + { + Top = LeaderboardScore.HEIGHT * 2, + Bottom = LeaderboardScore.HEIGHT * 3, + }; + return flow; + } + + private class ResultsMatchLeaderboardScore : MatchLeaderboardScore + { + public ResultsMatchLeaderboardScore(APIRoomScoreInfo score, int rank) + : base(score, rank) + { + } + + [BackgroundDependencyLoader] + private void load() + { + } + + } + } } } diff --git a/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs index 07429b0b89..bc78210484 100644 --- a/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs +++ b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs @@ -23,10 +23,10 @@ namespace osu.Game.Screens.Multi.Ranking.Types this.room = room; } - public FontAwesome Icon => FontAwesome.fa_list; + public FontAwesome Icon => FontAwesome.fa_users; public string Name => "Room Leaderboard"; - public virtual ResultsPage CreatePage() => new RoomRankingResultsPage(score, beatmap, room); + public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap, room); } } diff --git a/osu.Game/Screens/Play/SoloResults.cs b/osu.Game/Screens/Play/SoloResults.cs index 5e318e95d1..c06a5c3f68 100644 --- a/osu.Game/Screens/Play/SoloResults.cs +++ b/osu.Game/Screens/Play/SoloResults.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Play protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { new ScoreOverviewPageInfo(Score, Beatmap), - new BeatmapLeaderboardPageInfo(Score, Beatmap) + new LocalLeaderboardPageInfo(Score, Beatmap) }; } } diff --git a/osu.Game/Screens/Ranking/Pages/RankingResultsPage.cs b/osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs similarity index 85% rename from osu.Game/Screens/Ranking/Pages/RankingResultsPage.cs rename to osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs index 4c98e476c4..8ab45f2f1f 100644 --- a/osu.Game/Screens/Ranking/Pages/RankingResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs @@ -12,9 +12,9 @@ using osuTK; namespace osu.Game.Screens.Ranking.Pages { - public class RankingResultsPage : ResultsPage + public class LocalLeaderboardPage : ResultsPage { - public RankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap = null) + public LocalLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap = null) : base(score, beatmap) { } @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Ranking.Pages { new Box { - Colour = colours.GrayE, + Colour = colours.Gray6, RelativeSizeAxes = Axes.Both, }, new BeatmapLeaderboard diff --git a/osu.Game/Screens/Ranking/Types/BeatmapLeaderboardPageInfo.cs b/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs similarity index 59% rename from osu.Game/Screens/Ranking/Types/BeatmapLeaderboardPageInfo.cs rename to osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs index 2b192d4bcd..20eb75ff6f 100644 --- a/osu.Game/Screens/Ranking/Types/BeatmapLeaderboardPageInfo.cs +++ b/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs @@ -8,21 +8,21 @@ using osu.Game.Screens.Ranking.Pages; namespace osu.Game.Screens.Ranking.Types { - public class BeatmapLeaderboardPageInfo : IResultPageInfo + public class LocalLeaderboardPageInfo : IResultPageInfo { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; - public BeatmapLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap) + public LocalLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap) { this.score = score; this.beatmap = beatmap; } - public FontAwesome Icon => FontAwesome.fa_list; + public FontAwesome Icon => FontAwesome.fa_user; - public string Name => @"Beatmap Leaderboard"; + public string Name => @"Local Leaderboard"; - public ResultsPage CreatePage() => new RankingResultsPage(score, beatmap); + public ResultsPage CreatePage() => new LocalLeaderboardPage(score, beatmap); } } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 9f8726c86a..29ed7fe4dc 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -36,6 +36,8 @@ namespace osu.Game.Screens.Select.Leaderboards } } + protected override bool FadeTop => false; + [Resolved] private ScoreManager scoreManager { get; set; } From a3b6a3981c04c522d18b915b976916f066460149 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 16:14:30 +0900 Subject: [PATCH 316/355] Use .Equals() override instead of manual type checks --- osu.Game/Online/Multiplayer/Room.cs | 9 ++------- osu.Game/Online/Multiplayer/RoomStatus.cs | 3 +++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 80558b14db..5cf73b5617 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -88,14 +88,9 @@ namespace osu.Game.Online.Multiplayer if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id) Host.Value = other.Host; - if (Status.Value.GetType() != other.Status.Value.GetType()) - Status.Value = other.Status; - + Status.Value = other.Status; Availability.Value = other.Availability; - - if (Type.Value.GetType() != other.Type.Value.GetType()) - Type.Value = other.Type; - + Type.Value = other.Type; MaxParticipants.Value = other.MaxParticipants; ParticipantCount.Value = other.ParticipantCount.Value; Participants.Value = other.Participants.Value.ToArray(); diff --git a/osu.Game/Online/Multiplayer/RoomStatus.cs b/osu.Game/Online/Multiplayer/RoomStatus.cs index e2d84500a9..f5c339c71f 100644 --- a/osu.Game/Online/Multiplayer/RoomStatus.cs +++ b/osu.Game/Online/Multiplayer/RoomStatus.cs @@ -10,5 +10,8 @@ namespace osu.Game.Online.Multiplayer { public abstract string Message { get; } public abstract Color4 GetAppropriateColour(OsuColour colours); + + public override int GetHashCode() => GetType().GetHashCode(); + public override bool Equals(object obj) => GetType() == obj?.GetType(); } } From 50201e602eacbdc1a03c99f405c96734e2ab99ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 16:18:48 +0900 Subject: [PATCH 317/355] Combine implementations of status + end date info --- .../Screens/Multi/Components/EndDateInfo.cs | 32 ----- .../Multi/Components/RoomStatusInfo.cs | 111 ++++++++++++++++++ .../Multi/Lounge/Components/DrawableRoom.cs | 33 +----- .../Screens/Multi/Match/Components/Info.cs | 48 ++------ 4 files changed, 122 insertions(+), 102 deletions(-) delete mode 100644 osu.Game/Screens/Multi/Components/EndDateInfo.cs create mode 100644 osu.Game/Screens/Multi/Components/RoomStatusInfo.cs diff --git a/osu.Game/Screens/Multi/Components/EndDateInfo.cs b/osu.Game/Screens/Multi/Components/EndDateInfo.cs deleted file mode 100644 index c71ec04d33..0000000000 --- a/osu.Game/Screens/Multi/Components/EndDateInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Game.Graphics; - -namespace osu.Game.Screens.Multi.Components -{ - public class EndDateInfo : DrawableDate - { - public EndDateInfo() - : base(DateTimeOffset.UtcNow) - { - } - - protected override string Format() - { - var diffToNow = Date.Subtract(DateTimeOffset.Now); - - if (diffToNow.TotalSeconds < -5) - return $"Closed {base.Format()}"; - - if (diffToNow.TotalSeconds < 0) - return "Closed"; - - if (diffToNow.TotalSeconds < 5) - return "Closing soon"; - - return $"Closing {base.Format()}"; - } - } -} diff --git a/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs b/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs new file mode 100644 index 0000000000..ca93ea2366 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs @@ -0,0 +1,111 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.RoomStatuses; + +namespace osu.Game.Screens.Multi.Components +{ + public class RoomStatusInfo : CompositeDrawable + { + private readonly RoomBindings bindings = new RoomBindings(); + + public RoomStatusInfo(Room room) + { + bindings.Room = room; + + AutoSizeAxes = Axes.Both; + + StatusPart statusPart; + EndDatePart endDatePart; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + statusPart = new StatusPart + { + TextSize = 14, + Font = "Exo2.0-Bold" + }, + endDatePart = new EndDatePart { TextSize = 14 } + } + }; + + statusPart.EndDate.BindTo(bindings.EndDate); + statusPart.Status.BindTo(bindings.Status); + statusPart.Availability.BindTo(bindings.Availability); + endDatePart.EndDate.BindTo(bindings.EndDate); + } + + private class EndDatePart : DrawableDate + { + public readonly IBindable EndDate = new Bindable(); + + public EndDatePart() + : base(DateTimeOffset.UtcNow) + { + EndDate.BindValueChanged(d => Date = d); + } + + protected override string Format() + { + var diffToNow = Date.Subtract(DateTimeOffset.Now); + + if (diffToNow.TotalSeconds < -5) + return $"Closed {base.Format()}"; + + if (diffToNow.TotalSeconds < 0) + return "Closed"; + + if (diffToNow.TotalSeconds < 5) + return "Closing soon"; + + return $"Closing {base.Format()}"; + } + } + + private class StatusPart : EndDatePart + { + public readonly IBindable Status = new Bindable(); + public readonly IBindable Availability = new Bindable(); + + [Resolved] + private OsuColour colours { get; set; } + + public StatusPart() + { + EndDate.BindValueChanged(_ => Format()); + Status.BindValueChanged(_ => Format()); + Availability.BindValueChanged(_ => Format()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Text = Format(); + } + + protected override string Format() + { + if (!IsLoaded) + return string.Empty; + + RoomStatus status = Date < DateTimeOffset.Now ? new RoomStatusEnded() : Status.Value ?? new RoomStatusOpen(); + + this.FadeColour(status.GetAppropriateColour(colours), 100); + return $"{Availability.Value.GetDescription()}, {status.Message}"; + } + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 0540eed1aa..fb31864cc5 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -99,10 +99,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void load(OsuColour colours) { Box sideStrip; - OsuSpriteText status; ParticipantInfo participantInfo; OsuSpriteText name; - EndDateInfo endDate; Children = new Drawable[] { @@ -172,31 +170,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), Children = new Drawable[] { - status = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - Children = new Drawable[] - { - endDate = new EndDateInfo - { - TextSize = 14, - }, - beatmapTitle = new BeatmapTitle - { - TextSize = 14, - }, - } - } + new RoomStatusInfo(Room), + beatmapTitle = new BeatmapTitle { TextSize = 14 }, }, }, modeTypeInfo = new ModeTypeInfo @@ -220,12 +198,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); bindings.Name.BindValueChanged(n => name.Text = n, true); - bindings.EndDate.BindValueChanged(d => endDate.Date = d, true); bindings.Status.BindValueChanged(s => { - status.Text = s.Message; - - foreach (Drawable d in new Drawable[] { selectionBox, sideStrip, status }) + foreach (Drawable d in new Drawable[] { selectionBox, sideStrip }) d.FadeColour(s.GetAppropriateColour(colours), transition_duration); }, true); } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index 08ba370282..0aabc014c9 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Allocation; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -20,10 +18,6 @@ namespace osu.Game.Screens.Multi.Match.Components { public Action OnStart; - private readonly OsuSpriteText availabilityStatus; - - private OsuColour colours; - private readonly RoomBindings bindings = new RoomBindings(); public Info(Room room) @@ -33,9 +27,8 @@ namespace osu.Game.Screens.Multi.Match.Components ReadyButton readyButton; ViewBeatmapButton viewBeatmapButton; - OsuSpriteText name; - EndDateInfo endDate; HostInfo hostInfo; + RoomStatusInfo statusInfo; Children = new Drawable[] { @@ -65,9 +58,12 @@ namespace osu.Game.Screens.Multi.Match.Components Direction = FillDirection.Vertical, Children = new Drawable[] { - name = new OsuSpriteText { TextSize = 30 }, - availabilityStatus = new OsuSpriteText { TextSize = 14 }, - endDate = new EndDateInfo { TextSize = 14 } + new OsuSpriteText + { + TextSize = 30, + Current = bindings.Name + }, + new RoomStatusInfo(room), } }, hostInfo = new HostInfo(), @@ -98,37 +94,7 @@ namespace osu.Game.Screens.Multi.Match.Components readyButton.Beatmap.BindTo(bindings.CurrentBeatmap); hostInfo.Host.BindTo(bindings.Host); - bindings.Availability.BindValueChanged(_ => updateAvailabilityStatus()); - bindings.Status.BindValueChanged(_ => updateAvailabilityStatus()); - bindings.Name.BindValueChanged(n => name.Text = n); - bindings.EndDate.BindValueChanged(d => endDate.Date = d); - bindings.Room = room; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - this.colours = colours; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - updateAvailabilityStatus(); - } - - private void updateAvailabilityStatus() - { - if (!IsLoaded) - return; - - if (bindings.Status.Value != null) - { - availabilityStatus.FadeColour(bindings.Status.Value.GetAppropriateColour(colours), 100); - availabilityStatus.Text = $"{bindings.Availability.Value.GetDescription()}, {bindings.Status.Value.Message}"; - } - } } } From c614505b7cf39540ea539522ddcaf24c2e96d421 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 16:20:37 +0900 Subject: [PATCH 318/355] Revert unnecessary change to testcase --- osu.Game.Tests/Visual/TestCasePollingComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/TestCasePollingComponent.cs index 3f999f2b89..b4b9d465e5 100644 --- a/osu.Game.Tests/Visual/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/TestCasePollingComponent.cs @@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual }; }); - protected override double TimePerAction => 5000; + protected override double TimePerAction => 500; public class TestPoller : PollingComponent { From 8e031325dd1a4904a503be2760fb3c5f53bc9b22 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 16:28:17 +0900 Subject: [PATCH 319/355] CI fixes --- osu.Game/Online/Leaderboards/Leaderboard.cs | 1 - .../Multiplayer/GameTypes/GameTypeTag.cs | 5 ++- .../Multiplayer/GameTypes/GameTypeTagTeam.cs | 5 ++- .../GameTypes/GameTypeTeamVersus.cs | 5 ++- .../GameTypes/GameTypeTimeshift.cs | 3 ++ .../Multiplayer/GameTypes/GameTypeVersus.cs | 5 ++- .../Online/Multiplayer/GameTypes/VersusRow.cs | 5 ++- osu.Game/Online/Multiplayer/Room.cs | 1 - .../Multi/Match/Components/HostInfo.cs | 2 -- .../Match/Components/MatchLeaderboard.cs | 23 ------------- .../Match/Components/MatchLeaderboardScore.cs | 33 +++++++++++++++++++ .../Match/Components/MatchSettingsOverlay.cs | 1 - .../Ranking/Pages/RoomLeaderboardPage.cs | 1 - osu.Game/Screens/Multi/RoomManager.cs | 1 - 14 files changed, 56 insertions(+), 35 deletions(-) create mode 100644 osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index a30a3c4254..0c61491f9d 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -88,7 +88,6 @@ namespace osu.Game.Online.Leaderboards AutoSizeAxes = Axes.Y, Spacing = new Vector2(0f, 5f), Padding = new MarginPadding { Top = 10, Bottom = 5 }, - }; private TScope scope; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs index d31439f0fe..c9d16662ba 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Game.Graphics; using osuTK; @@ -21,4 +24,4 @@ namespace osu.Game.Online.Multiplayer.GameTypes }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs index 74c8e76b46..952d1a39ac 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -38,4 +41,4 @@ namespace osu.Game.Online.Multiplayer.GameTypes }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs index 74c2c00c3b..49e7cef88d 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -26,4 +29,4 @@ namespace osu.Game.Online.Multiplayer.GameTypes }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs index e87f8a9696..ab8658dfb2 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Game.Graphics; using osuTK; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs index b6d832490f..c74ce63470 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Game.Graphics; @@ -16,4 +19,4 @@ namespace osu.Game.Online.Multiplayer.GameTypes }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs b/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs index 2b150fc6f0..b4d8279d02 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -49,4 +52,4 @@ namespace osu.Game.Online.Multiplayer.GameTypes }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 5cf73b5617..0d6a8ae3a8 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -50,7 +50,6 @@ namespace osu.Game.Online.Multiplayer [JsonIgnore] public Bindable> Participants { get; private set; } = new Bindable>(Enumerable.Empty()); - public Bindable ParticipantCount { get; private set; } = new Bindable(); // todo: TEMPORARY diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index 437b4cfe1b..993dccce44 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -42,8 +42,6 @@ namespace osu.Game.Screens.Multi.Match.Components } }; - - Host.BindValueChanged(updateHost); } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index dd5a73817f..864191105f 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -4,13 +4,11 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Online.Multiplayer; -using osu.Game.Scoring; namespace osu.Game.Screens.Multi.Match.Components { @@ -57,27 +55,6 @@ namespace osu.Game.Screens.Multi.Match.Components protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) => new MatchLeaderboardScore(model, index); } - public class MatchLeaderboardScore : LeaderboardScore - { - public MatchLeaderboardScore(APIRoomScoreInfo score, int rank) - : base(score, rank) - { - } - - [BackgroundDependencyLoader] - private void load() - { - RankContainer.Alpha = 0; - } - - protected override IEnumerable GetStatistics(ScoreInfo model) => new[] - { - new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), - new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()), - new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedBeatmaps.ToString()), - }; - } - public enum MatchLeaderboardScope { Overall diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs new file mode 100644 index 0000000000..ebd69b24fc --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs @@ -0,0 +1,33 @@ +// 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.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; +using osu.Game.Scoring; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class MatchLeaderboardScore : LeaderboardScore + { + public MatchLeaderboardScore(APIRoomScoreInfo score, int rank) + : base(score, rank) + { + } + + [BackgroundDependencyLoader] + private void load() + { + RankContainer.Alpha = 0; + } + + protected override IEnumerable GetStatistics(ScoreInfo model) => new[] + { + new LeaderboardScoreStatistic(FontAwesome.fa_crosshairs, "Accuracy", string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy)), + new LeaderboardScoreStatistic(FontAwesome.fa_refresh, "Total Attempts", ((APIRoomScoreInfo)model).TotalAttempts.ToString()), + new LeaderboardScoreStatistic(FontAwesome.fa_check, "Completed Beatmaps", ((APIRoomScoreInfo)model).CompletedBeatmaps.ToString()), + }; + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 5d16f0f8cd..1210b9379f 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -294,7 +294,6 @@ namespace osu.Game.Screens.Multi.Match.Components bindings.Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(room, onSuccess, onError); processingOverlay.Show(); diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index 8423a76a36..3673944837 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -132,7 +132,6 @@ namespace osu.Game.Screens.Multi.Ranking.Pages private void load() { } - } } } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index ceecaf5443..6810fdebe9 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -40,7 +40,6 @@ namespace osu.Game.Screens.Multi TimeBetweenPolls = 5000; } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From f70e60747f1be3f13c0f0c3993bc8ee412801dfc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 16:54:14 +0900 Subject: [PATCH 320/355] Remove option for 1-minute duration --- osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 1210b9379f..72136b1874 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -157,7 +157,6 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.X, Items = new[] { - TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(30), TimeSpan.FromHours(1), TimeSpan.FromHours(2), From bd0576537e27cb7343165dc747861d461df06b1f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 17:12:47 +0900 Subject: [PATCH 321/355] Forcefully exit multiplayer if API loses connectivity --- osu.Game/Screens/Multi/Multiplayer.cs | 32 ++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 499198d800..eb6acdd551 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -21,7 +21,7 @@ using osuTK; namespace osu.Game.Screens.Multi { [Cached] - public class Multiplayer : OsuScreen + public class Multiplayer : OsuScreen, IOnlineComponent { private readonly MultiplayerWaveContainer waves; @@ -98,6 +98,30 @@ namespace osu.Game.Screens.Multi loungeSubScreen.Exited += _ => Exit(); } + [BackgroundDependencyLoader] + private void load() + { + api.Register(this); + } + + public void APIStateChanged(APIAccess api, APIState state) + { + if (state != APIState.Online) + forcefullyExit(); + } + + private void forcefullyExit() + { + // This is temporary since we don't currently have a way to force screens to be exited + if (IsCurrentScreen) + Exit(); + else + { + MakeCurrent(); + Schedule(forcefullyExit); + } + } + protected override void OnEntering(Screen last) { Content.FadeIn(); @@ -196,6 +220,12 @@ namespace osu.Game.Screens.Multi currentScreen = (OsuScreen)newScreen; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + api?.Unregister(this); + } + private class MultiplayerWaveContainer : WaveContainer { protected override bool StartHidden => true; From ea1309e76883481d95b5d60b70311abf696d727e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 17:15:43 +0900 Subject: [PATCH 322/355] Fix missing bind --- osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index a7fa592323..47f915b739 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -171,6 +171,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components participantInfo.Participants.BindTo(bindings.Participants); participantCount.Participants.BindTo(bindings.Participants); + participantCount.ParticipantCount.BindTo(bindings.ParticipantCount); participantCount.MaxParticipants.BindTo(bindings.MaxParticipants); beatmapTypeInfo.Type.BindTo(bindings.Type); From dae710f9a655a0a48bdda63b5756365bfb0cf3b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 17:29:55 +0900 Subject: [PATCH 323/355] Make leaderboard top not fade by default --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs | 2 ++ osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 0c61491f9d..f3bf16a05f 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -265,7 +265,7 @@ namespace osu.Game.Online.Leaderboards } protected virtual bool FadeBottom => true; - protected virtual bool FadeTop => true; + protected virtual bool FadeTop => false; protected override void UpdateAfterChildren() { diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index 3673944837..54528e5503 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -107,6 +107,8 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { } + protected override bool FadeTop => true; + protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) => new ResultsMatchLeaderboardScore(model, index); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 29ed7fe4dc..9f8726c86a 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -36,8 +36,6 @@ namespace osu.Game.Screens.Select.Leaderboards } } - protected override bool FadeTop => false; - [Resolved] private ScoreManager scoreManager { get; set; } From b0e8561ad35940b82459710ceb30d783330396eb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 17:48:10 +0900 Subject: [PATCH 324/355] Fix ruleset not changing correctly --- osu.Game/Screens/Multi/RoomBindings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/RoomBindings.cs b/osu.Game/Screens/Multi/RoomBindings.cs index 9a38ba1f60..dc2547268d 100644 --- a/osu.Game/Screens/Multi/RoomBindings.cs +++ b/osu.Game/Screens/Multi/RoomBindings.cs @@ -101,6 +101,6 @@ namespace osu.Game.Screens.Multi public IBindable> CurrentMods => currentMods; private readonly Bindable currentRuleset = new Bindable(); - public IBindable CurrentRuleset = new Bindable(); + public IBindable CurrentRuleset => currentRuleset; } } From d6c53e38510035e6734c7e793867376e082064cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 18:09:42 +0900 Subject: [PATCH 325/355] Cancel old web requests when changing filter modes --- osu.Game/Screens/Multi/RoomManager.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 6810fdebe9..2ab756e92a 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -109,6 +109,8 @@ namespace osu.Game.Screens.Multi PollImmediately(); } + private GetRoomsRequest pollReq; + protected override Task Poll() { if (!api.IsLoggedIn) @@ -116,7 +118,8 @@ namespace osu.Game.Screens.Multi var tcs = new TaskCompletionSource(); - var pollReq = new GetRoomsRequest(currentFilter.PrimaryFilter); + pollReq?.Cancel(); + pollReq = new GetRoomsRequest(currentFilter.PrimaryFilter); pollReq.Success += result => { From 9a5630b3d5aff8665729543ebabe23553c452142 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 18:10:49 +0900 Subject: [PATCH 326/355] Fix working beatmap not being updated --- .../Screens/Multi/Match/MatchSubScreen.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 5cd5d9e76a..9ff1b84b41 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -119,6 +119,12 @@ namespace osu.Game.Screens.Multi.Match chat.Exit += Exit; } + [BackgroundDependencyLoader] + private void load() + { + beatmapManager.ItemAdded += beatmapAdded; + } + protected override bool OnExiting(Screen next) { manager?.PartRoom(); @@ -155,6 +161,21 @@ namespace osu.Game.Screens.Multi.Match game?.ForcefullySetRuleset(ruleset); } + private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() => + { + if (Beatmap.Value != beatmapManager.DefaultBeatmap) + return; + + if (bindings.CurrentBeatmap.Value == null) + return; + + // Try to retrieve the corresponding local beatmap + var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == bindings.CurrentBeatmap.Value.OnlineBeatmapID); + + if (localBeatmap != null) + game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); + }); + private void addPlaylistItem(PlaylistItem item) { bindings.Playlist.Clear(); @@ -176,5 +197,13 @@ namespace osu.Game.Screens.Multi.Match break; } } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmapManager != null) + beatmapManager.ItemAdded -= beatmapAdded; + } } } From eaba9e13789e1287f0427a3a84786b1dd21de392 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 18:16:17 +0900 Subject: [PATCH 327/355] Fix mode icon not being updated for correct ruleset --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 10 ++++++---- osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs | 4 +++- osu.Game/Screens/Multi/Components/ModeTypeInfo.cs | 5 ++++- .../Screens/Multi/Lounge/Components/DrawableRoom.cs | 3 ++- .../Screens/Multi/Lounge/Components/RoomInspector.cs | 3 ++- osu.Game/Screens/Multi/Match/Components/Header.cs | 1 + 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 14162c35c0..fe6200472f 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Rulesets; using osuTK; using osuTK.Graphics; @@ -16,15 +17,16 @@ namespace osu.Game.Beatmaps.Drawables { public class DifficultyIcon : DifficultyColouredContainer { - private readonly BeatmapInfo beatmap; + private readonly RulesetInfo ruleset; - public DifficultyIcon(BeatmapInfo beatmap) + public DifficultyIcon(BeatmapInfo beatmap, RulesetInfo ruleset = null) : base(beatmap) { if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); - this.beatmap = beatmap; + this.ruleset = ruleset ?? beatmap.Ruleset; + Size = new Vector2(20); } @@ -58,7 +60,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) - Icon = beatmap.Ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o } + Icon = ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o } } }; } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index a06eaa35dc..04ac0cc4c3 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.Chat; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; using osuTK; namespace osu.Game.Screens.Multi.Components @@ -16,7 +17,7 @@ namespace osu.Game.Screens.Multi.Components public class BeatmapTypeInfo : CompositeDrawable { public readonly IBindable Beatmap = new Bindable(); - + public readonly IBindable Ruleset = new Bindable(); public readonly IBindable Type = new Bindable(); public BeatmapTypeInfo() @@ -56,6 +57,7 @@ namespace osu.Game.Screens.Multi.Components }; modeTypeInfo.Beatmap.BindTo(Beatmap); + modeTypeInfo.Ruleset.BindTo(Ruleset); modeTypeInfo.Type.BindTo(Type); beatmapTitle.Beatmap.BindTo(Beatmap); diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 8104244084..aad409e2c7 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; using osuTK; namespace osu.Game.Screens.Multi.Components @@ -19,6 +20,7 @@ namespace osu.Game.Screens.Multi.Components private readonly Container rulesetContainer; public readonly IBindable Beatmap = new Bindable(); + public readonly IBindable Ruleset = new Bindable(); public readonly IBindable Type = new Bindable(); public ModeTypeInfo() @@ -47,6 +49,7 @@ namespace osu.Game.Screens.Multi.Components }; Beatmap.BindValueChanged(updateBeatmap); + Ruleset.BindValueChanged(_ => updateBeatmap(Beatmap.Value)); Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }); } @@ -55,7 +58,7 @@ namespace osu.Game.Screens.Multi.Components if (beatmap != null) { rulesetContainer.FadeIn(transition_duration); - rulesetContainer.Child = new DifficultyIcon(beatmap) { Size = new Vector2(height) }; + rulesetContainer.Child = new DifficultyIcon(beatmap, Ruleset.Value) { Size = new Vector2(height) }; } else rulesetContainer.FadeOut(transition_duration); diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index fb31864cc5..219121cb53 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -191,8 +191,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components background.Beatmap.BindTo(bindings.CurrentBeatmap); modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); - beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap); + modeTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); modeTypeInfo.Type.BindTo(bindings.Type); + beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap); participantInfo.Host.BindTo(bindings.Host); participantInfo.Participants.BindTo(bindings.Participants); participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 47f915b739..47f5182c39 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -174,9 +174,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components participantCount.ParticipantCount.BindTo(bindings.ParticipantCount); participantCount.MaxParticipants.BindTo(bindings.MaxParticipants); + beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); + beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); beatmapTypeInfo.Type.BindTo(bindings.Type); background.Beatmap.BindTo(bindings.CurrentBeatmap); - beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); bindings.Status.BindValueChanged(displayStatus); bindings.Participants.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 4f4d5a1d4e..4cb6d7a4e0 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -112,6 +112,7 @@ namespace osu.Game.Screens.Multi.Match.Components }; beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); + beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); beatmapTypeInfo.Type.BindTo(bindings.Type); background.Beatmap.BindTo(bindings.CurrentBeatmap); bindings.CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true); From 31db768bdc44a46f6f34f5d2afdec09d27b78de9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 19:18:27 +0900 Subject: [PATCH 328/355] Hide version overlay when not in main menu --- osu.Game/OsuGame.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6a5f9656d1..cc923bb91f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -716,10 +716,16 @@ namespace osu.Game this.ruleset.Disabled = rulesetDisabled; } - private void screenAdded(Screen newScreen) + protected virtual void ScreenChanged(OsuScreen current, Screen newScreen) { currentScreen = (OsuScreen)newScreen; - Logger.Log($"Screen changed → {currentScreen}"); + } + + private void screenAdded(Screen newScreen) + { + ScreenChanged(currentScreen, newScreen); + Logger.Log($"Screen changed → {newScreen}"); + newScreen.ModePushed += screenAdded; newScreen.Exited += screenRemoved; @@ -727,7 +733,7 @@ namespace osu.Game private void screenRemoved(Screen newScreen) { - currentScreen = (OsuScreen)newScreen; + ScreenChanged(currentScreen, newScreen); Logger.Log($"Screen changed ← {currentScreen}"); if (newScreen == null) From bdadd1bba2b7e8e38c6fbe220296f75be94b3ed2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 19:22:24 +0900 Subject: [PATCH 329/355] Add actual changes --- osu.Desktop/Overlays/VersionManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index f31bba1e1e..c1fd34d009 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -128,11 +128,12 @@ namespace osu.Desktop.Overlays protected override void PopIn() { - this.FadeIn(1000); + this.FadeIn(1400, Easing.OutQuint); } protected override void PopOut() { + this.FadeOut(500, Easing.OutQuint); } } } From c6d017b503cd5ff8ab6d75f52995923ef5460826 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 19:23:58 +0900 Subject: [PATCH 330/355] And some more --- osu.Desktop/OsuGameDesktop.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 93fd3935c6..bd9ba3501f 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -15,12 +15,16 @@ using Microsoft.Win32; using osu.Desktop.Updater; using osu.Framework; using osu.Framework.Platform.Windows; +using osu.Framework.Screens; +using osu.Game.Screens; +using osu.Game.Screens.Menu; namespace osu.Desktop { internal class OsuGameDesktop : OsuGame { private readonly bool noVersionOverlay; + private VersionManager versionManager; public OsuGameDesktop(string[] args = null) : base(args) @@ -46,7 +50,7 @@ namespace osu.Desktop if (!noVersionOverlay) { - LoadComponentAsync(new VersionManager { Depth = int.MinValue }, v => + LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v => { Add(v); v.State = Visibility.Visible; @@ -59,6 +63,21 @@ namespace osu.Desktop } } + protected override void ScreenChanged(OsuScreen current, Screen newScreen) + { + base.ScreenChanged(current, newScreen); + switch (newScreen) + { + case Intro _: + case MainMenu _: + versionManager.State = Visibility.Visible; + break; + default: + versionManager.State = Visibility.Hidden; + break; + } + } + public override void SetHost(GameHost host) { base.SetHost(host); From ab5f6e149c82ebd2cd3ea8f2564df10c75efb991 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 19:25:56 +0900 Subject: [PATCH 331/355] Remvoe extra newline --- osu.Game/OsuGame.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cc923bb91f..2a4c812401 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -726,7 +726,6 @@ namespace osu.Game ScreenChanged(currentScreen, newScreen); Logger.Log($"Screen changed → {newScreen}"); - newScreen.ModePushed += screenAdded; newScreen.Exited += screenRemoved; } From c5764ded1c26998cfdb917d566a0abd7ec65b50c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 20:03:32 +0900 Subject: [PATCH 332/355] Fix infinite polling rate in certain scenarios --- osu.Game/Online/PollingComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index 07b6db2dc2..36a42b5d0a 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -112,7 +112,7 @@ namespace osu.Game.Online pollingActive = false; if (scheduledPoll == null) - scheduleNextPoll(); + pollIfNecessary(); } private void scheduleNextPoll() From 1ce33cb6dac082911fefb5d3f3f0bd6a71996d20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 20:06:07 +0900 Subject: [PATCH 333/355] Adjust polling rate based on current screen and idle state --- osu.Game/Screens/Multi/Multiplayer.cs | 45 ++++++++++++++++++++------- osu.Game/Screens/Multi/RoomManager.cs | 5 --- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index eb6acdd551..6b1c614ff6 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -2,14 +2,17 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.BeatmapSet.Buttons; @@ -25,12 +28,12 @@ namespace osu.Game.Screens.Multi { private readonly MultiplayerWaveContainer waves; - public override bool AllowBeatmapRulesetChange => currentScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; + public override bool AllowBeatmapRulesetChange => currentSubScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; private readonly OsuButton createButton; private readonly LoungeSubScreen loungeSubScreen; - private OsuScreen currentScreen; + private OsuScreen currentSubScreen; [Cached(Type = typeof(IRoomManager))] private RoomManager roomManager; @@ -98,10 +101,25 @@ namespace osu.Game.Screens.Multi loungeSubScreen.Exited += _ => Exit(); } + private readonly IBindable isIdle = new BindableBool(); + [BackgroundDependencyLoader] - private void load() + private void load(IdleTracker idleTracker) { api.Register(this); + isIdle.BindTo(idleTracker.IsIdle); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + isIdle.BindValueChanged(updatePollingRate, true); + } + + private void updatePollingRate(bool idle) + { + roomManager.TimeBetweenPolls = !IsCurrentScreen || !(currentSubScreen is LoungeSubScreen) ? 0 : (idle ? 120000 : 15000); + Logger.Log($"Polling adjusted to {roomManager.TimeBetweenPolls}"); } public void APIStateChanged(APIAccess api, APIState state) @@ -136,11 +154,9 @@ namespace osu.Game.Screens.Multi Content.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); - var track = Beatmap.Value.Track; - if (track != null) - track.Looping = false; - + cancelLooping(); loungeSubScreen.MakeCurrent(); + updatePollingRate(isIdle.Value); return base.OnExiting(next); } @@ -151,6 +167,8 @@ namespace osu.Game.Screens.Multi Content.FadeIn(250); Content.ScaleTo(1, 250, Easing.OutSine); + + updatePollingRate(isIdle.Value); } protected override void OnSuspending(Screen next) @@ -159,6 +177,7 @@ namespace osu.Game.Screens.Multi Content.FadeOut(250); cancelLooping(); + roomManager.TimeBetweenPolls = 0; base.OnSuspending(next); } @@ -183,7 +202,7 @@ namespace osu.Game.Screens.Multi if (!IsCurrentScreen) return; - if (currentScreen is MatchSubScreen) + if (currentSubScreen is MatchSubScreen) { var track = Beatmap.Value.Track; if (track != null) @@ -200,13 +219,14 @@ namespace osu.Game.Screens.Multi createButton.Hide(); } - else if (currentScreen is LoungeSubScreen) + else if (currentSubScreen is LoungeSubScreen) createButton.Show(); } private void screenAdded(Screen newScreen) { - currentScreen = (OsuScreen)newScreen; + currentSubScreen = (OsuScreen)newScreen; + updatePollingRate(isIdle.Value); newScreen.ModePushed += screenAdded; newScreen.Exited += screenRemoved; @@ -214,10 +234,11 @@ namespace osu.Game.Screens.Multi private void screenRemoved(Screen newScreen) { - if (currentScreen is MatchSubScreen) + if (currentSubScreen is MatchSubScreen) cancelLooping(); - currentScreen = (OsuScreen)newScreen; + currentSubScreen = (OsuScreen)newScreen; + updatePollingRate(isIdle.Value); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 2ab756e92a..6fe2307d8b 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -35,11 +35,6 @@ namespace osu.Game.Screens.Multi [Resolved] private BeatmapManager beatmaps { get; set; } - public RoomManager() - { - TimeBetweenPolls = 5000; - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 4a4bc8955d717630c74d17deb6a6b0a13a8a29af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 20:08:16 +0900 Subject: [PATCH 334/355] Fix crash on startup when specifying --no-version-overlay --- osu.Desktop/OsuGameDesktop.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index bd9ba3501f..2eeb112450 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -70,10 +70,12 @@ namespace osu.Desktop { case Intro _: case MainMenu _: - versionManager.State = Visibility.Visible; + if (versionManager != null) + versionManager.State = Visibility.Visible; break; default: - versionManager.State = Visibility.Hidden; + if (versionManager != null) + versionManager.State = Visibility.Hidden; break; } } From 31baf0086fa0096b07a4ce23c9464b3ee2c944ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 20:17:27 +0900 Subject: [PATCH 335/355] Optional idle tracker --- osu.Game/Screens/Multi/Multiplayer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 6b1c614ff6..ce0eddbee3 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -103,11 +103,13 @@ namespace osu.Game.Screens.Multi private readonly IBindable isIdle = new BindableBool(); - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(IdleTracker idleTracker) { api.Register(this); - isIdle.BindTo(idleTracker.IsIdle); + + if (idleTracker != null) + isIdle.BindTo(idleTracker.IsIdle); } protected override void LoadComplete() From 50b51a168e754fb4d4a243697c4a1fe72e95a37b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 21:12:32 +0900 Subject: [PATCH 336/355] Always submit standardised scores --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 18 +++++++++++++----- osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs | 11 +++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0ebea9c2d0..ebcf78435c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -167,6 +167,8 @@ namespace osu.Game.Rulesets.Scoring score.Rank = Rank; score.Date = DateTimeOffset.Now; } + + public abstract double GetStandardisedScore(); } public class ScoreProcessor : ScoreProcessor @@ -340,18 +342,24 @@ namespace osu.Game.Rulesets.Scoring if (rollingMaxBaseScore != 0) Accuracy.Value = baseScore / rollingMaxBaseScore; - switch (Mode.Value) + TotalScore.Value = getScore(Mode.Value); + } + + private double getScore(ScoringMode mode) + { + switch (mode) { + default: case ScoringMode.Standardised: - TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; - break; + return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; case ScoringMode.Classic: // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) - TotalScore.Value = bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25); - break; + return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25); } } + public override double GetStandardisedScore() => getScore(ScoringMode.Standardised); + protected override void Reset(bool storeResults) { if (storeResults) diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 0a7c11ecc5..84d0ca3621 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.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; using System.Diagnostics; using System.Threading; using osu.Framework.Allocation; @@ -60,16 +61,22 @@ namespace osu.Game.Screens.Multi.Play } protected override ScoreInfo CreateScore() + { + submitScore(); + return base.CreateScore(); + } + + private void submitScore() { var score = base.CreateScore(); + score.TotalScore = (int)Math.Round(ScoreProcessor.GetStandardisedScore()); + Debug.Assert(token != null); var request = new SubmitRoomScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score); request.Failure += e => Logger.Error(e, "Failed to submit score"); api.Queue(request); - - return score; } protected override Results CreateResults(ScoreInfo score) => new MatchResults(score, room); From fb10d158703c6bb25ba6f70899cb80083d2017d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 21:52:09 +0900 Subject: [PATCH 337/355] Populate statistics for all rulesets' scores --- .../Scoring/OsuScoreProcessor.cs | 17 ----------------- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 9b3da1b8a8..7cd78c8be7 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -9,7 +9,6 @@ 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 { @@ -22,7 +21,6 @@ namespace osu.Game.Rulesets.Osu.Scoring private float hpDrainRate; - private readonly Dictionary scoreResultCounts = new Dictionary(); private readonly Dictionary comboResultCounts = new Dictionary(); protected override void ApplyBeatmap(Beatmap beatmap) @@ -35,21 +33,9 @@ namespace osu.Game.Rulesets.Osu.Scoring protected override void Reset(bool storeResults) { base.Reset(storeResults); - - scoreResultCounts.Clear(); comboResultCounts.Clear(); } - public override void PopulateScore(ScoreInfo score) - { - base.PopulateScore(score); - - 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; protected override void ApplyResult(JudgementResult result) @@ -59,10 +45,7 @@ namespace osu.Game.Rulesets.Osu.Scoring var osuResult = (OsuJudgementResult)result; if (result.Type != HitResult.None) - { - scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1; - } switch (result.Type) { diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ebcf78435c..b2a1bfaabd 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -2,8 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Configuration; +using osu.Framework.Extensions; using osu.Framework.Extensions.TypeExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -155,6 +157,8 @@ namespace osu.Game.Rulesets.Scoring AllJudged?.Invoke(); } + private readonly Dictionary scoreResultCounts = new Dictionary(); + /// /// Retrieve a score populated with data for the current play this processor is responsible for. /// @@ -166,6 +170,13 @@ namespace osu.Game.Rulesets.Scoring score.Accuracy = Math.Round(Accuracy, 4); score.Rank = Rank; score.Date = DateTimeOffset.Now; + + score.Statistics[HitResult.Perfect] = scoreResultCounts.GetOrDefault(HitResult.Perfect); + score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great); + score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good); + score.Statistics[HitResult.Ok] = scoreResultCounts.GetOrDefault(HitResult.Ok); + score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh); + score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss); } public abstract double GetStandardisedScore(); @@ -275,6 +286,8 @@ namespace osu.Game.Rulesets.Scoring updateScore(); } + private readonly Dictionary scoreResultCounts = new Dictionary(); + /// /// Applies the score change of a to this . /// @@ -286,6 +299,9 @@ namespace osu.Game.Rulesets.Scoring JudgedHits++; + if (result.Type != HitResult.None) + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; + if (result.Judgement.AffectsCombo) { switch (result.Type) @@ -362,6 +378,8 @@ namespace osu.Game.Rulesets.Scoring protected override void Reset(bool storeResults) { + scoreResultCounts.Clear(); + if (storeResults) { MaxHits = JudgedHits; From 5977fc838ffc58037e9afa1865cd3963319c420e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 21:59:08 +0900 Subject: [PATCH 338/355] Limit available durations for the time being --- .../Screens/Multi/Match/Components/MatchSettingsOverlay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 72136b1874..68c97d16eb 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -163,10 +163,10 @@ namespace osu.Game.Screens.Multi.Match.Components TimeSpan.FromHours(4), TimeSpan.FromHours(8), TimeSpan.FromHours(12), - TimeSpan.FromHours(16), + //TimeSpan.FromHours(16), TimeSpan.FromHours(24), - TimeSpan.FromDays(3), - TimeSpan.FromDays(7) + //TimeSpan.FromDays(3), + //TimeSpan.FromDays(7) } } }, From 101fdf993ef1bf4de4111c8f9936cc47b9603646 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 21:59:43 +0900 Subject: [PATCH 339/355] Ensure mods are set prior to starting play --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 9ff1b84b41..55a5a2c85e 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.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 System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,7 +11,6 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; using osu.Game.Screens.Play; @@ -136,7 +134,6 @@ namespace osu.Game.Screens.Multi.Match base.LoadComplete(); bindings.CurrentBeatmap.BindValueChanged(setBeatmap, true); - bindings.CurrentMods.BindValueChanged(setMods, true); bindings.CurrentRuleset.BindValueChanged(setRuleset, true); } @@ -148,11 +145,6 @@ namespace osu.Game.Screens.Multi.Match game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); } - private void setMods(IEnumerable mods) - { - Beatmap.Value.Mods.Value = mods.ToArray(); - } - private void setRuleset(RulesetInfo ruleset) { if (ruleset == null) @@ -184,6 +176,8 @@ namespace osu.Game.Screens.Multi.Match private void onStart() { + Beatmap.Value.Mods.Value = bindings.CurrentMods.Value.ToArray(); + switch (bindings.Type.Value) { default: From cf079690e528cadd4387402ca2a050d388604796 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 22:13:51 +0900 Subject: [PATCH 340/355] Use LargeTextureStore for online retrievals --- osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index 883c05f1e4..e09da2fb72 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -23,7 +23,7 @@ namespace osu.Game.Beatmaps.Drawables } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(LargeTextureStore textures) { string resource = null; From a62405d82d7711a642cef677596b5ba563c07c12 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 22:16:58 +0900 Subject: [PATCH 341/355] Fix plays with mods not submitting --- osu.Game/Screens/Play/Player.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f2390318b0..c102fb0223 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -301,7 +301,8 @@ namespace osu.Game.Screens.Play { Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset, - User = api.LocalUser.Value + Mods = Beatmap.Value.Mods.Value.ToArray(), + User = api.LocalUser.Value, }; ScoreProcessor.PopulateScore(score); From 99ed0098386d73ffd8c7431672568cdf0e899b67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 27 Dec 2018 22:31:40 +0900 Subject: [PATCH 342/355] Fix extra hit result types showing on ranking screen --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b2a1bfaabd..e86c218797 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Framework.Extensions.TypeExtensions; @@ -59,6 +60,11 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableInt Combo = new BindableInt(); + /// + /// Create a for this processor. + /// + protected virtual HitWindows CreateHitWindows() => new HitWindows(); + /// /// The current rank. /// @@ -171,12 +177,10 @@ namespace osu.Game.Rulesets.Scoring score.Rank = Rank; score.Date = DateTimeOffset.Now; - score.Statistics[HitResult.Perfect] = scoreResultCounts.GetOrDefault(HitResult.Perfect); - score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great); - score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good); - score.Statistics[HitResult.Ok] = scoreResultCounts.GetOrDefault(HitResult.Ok); - score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh); - score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss); + var hitWindows = CreateHitWindows(); + + foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => hitWindows.IsHitResultAllowed(r))) + score.Statistics[result] = scoreResultCounts.GetOrDefault(result); } public abstract double GetStandardisedScore(); From b64932f6db381220cc7659bdc0caf2722a585936 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 22:36:57 +0900 Subject: [PATCH 343/355] Implement hit windows --- .../Objects/CatchHitWindows.cs | 23 +++++++++++++++++++ .../Scoring/CatchScoreProcessor.cs | 3 +++ .../Scoring/ManiaScoreProcessor.cs | 3 +++ .../Scoring/TaikoScoreProcessor.cs | 3 +++ 4 files changed, 32 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs new file mode 100644 index 0000000000..1cf2694a90 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Catch.Objects +{ + public class CatchHitWindows : HitWindows + { + public override bool IsHitResultAllowed(HitResult result) + { + switch (result) + { + case HitResult.Perfect: + case HitResult.Miss: + return true; + } + + return false; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 778d972b52..57f4355d6a 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -5,6 +5,7 @@ using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -41,5 +42,7 @@ namespace osu.Game.Rulesets.Catch.Scoring Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; } + + protected override HitWindows CreateHitWindows() => new CatchHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 12b32c46ee..20a665c314 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -157,5 +158,7 @@ namespace osu.Game.Rulesets.Mania.Scoring } } } + + protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 318efdbf3e..87481c800d 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -3,6 +3,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.UI; @@ -65,5 +66,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring Health.Value = 0; } + + protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); } } From 338b95dd6304732b4458bd54fa5fe396bee6f2e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 27 Dec 2018 22:48:24 +0900 Subject: [PATCH 344/355] Fix none result getting included --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index e86c218797..ae0f0dda50 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Scoring var hitWindows = CreateHitWindows(); - foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => hitWindows.IsHitResultAllowed(r))) + foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r))) score.Statistics[result] = scoreResultCounts.GetOrDefault(result); } From 5c1280c0921e1a3e952ae71e9233b8f7b2902081 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 28 Dec 2018 00:14:00 +0900 Subject: [PATCH 345/355] Fix missing hitwindows --- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 7cd78c8be7..a24efe4a1e 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; @@ -72,5 +73,7 @@ namespace osu.Game.Rulesets.Osu.Scoring } protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); + + protected override HitWindows CreateHitWindows() => new OsuHitWindows(); } } From be86281c729945106e07a9330ab2e9bc102a63e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 28 Dec 2018 00:24:02 +0900 Subject: [PATCH 346/355] Fix score results not populated --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ae0f0dda50..4b3012192d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -163,8 +163,6 @@ namespace osu.Game.Rulesets.Scoring AllJudged?.Invoke(); } - private readonly Dictionary scoreResultCounts = new Dictionary(); - /// /// Retrieve a score populated with data for the current play this processor is responsible for. /// @@ -180,9 +178,11 @@ namespace osu.Game.Rulesets.Scoring var hitWindows = CreateHitWindows(); foreach (var result in Enum.GetValues(typeof(HitResult)).OfType().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r))) - score.Statistics[result] = scoreResultCounts.GetOrDefault(result); + score.Statistics[result] = GetStatistic(result); } + protected abstract int GetStatistic(HitResult result); + public abstract double GetStandardisedScore(); } @@ -378,6 +378,8 @@ namespace osu.Game.Rulesets.Scoring } } + protected override int GetStatistic(HitResult result) => scoreResultCounts.GetOrDefault(result); + public override double GetStandardisedScore() => getScore(ScoringMode.Standardised); protected override void Reset(bool storeResults) From f2f1ba8cbe0c82254a37d19316b94ff9b501caf6 Mon Sep 17 00:00:00 2001 From: Lanyun Hou Date: Fri, 28 Dec 2018 00:43:20 +0800 Subject: [PATCH 347/355] Fix typo in line 42 --- osu.Game/Online/PollingComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index 36a42b5d0a..6296608e5d 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -39,7 +39,7 @@ namespace osu.Game.Online /// /// /// - /// The initial time in milliseconds to wait between polls. Setting to zero stops al polling. + /// The initial time in milliseconds to wait between polls. Setting to zero stops all polling. protected PollingComponent(double timeBetweenPolls = 0) { TimeBetweenPolls = timeBetweenPolls; From a7db0bbb91695dc7d84a2aca63feedc8ecf05f62 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 28 Dec 2018 01:45:19 +0900 Subject: [PATCH 348/355] Sort rooms based on their API position --- .../Visual/TestCaseLoungeRoomsContainer.cs | 2 ++ .../Visual/TestCaseMatchSettingsOverlay.cs | 2 ++ osu.Game/Online/Multiplayer/Room.cs | 8 ++++++++ osu.Game/Screens/Multi/IRoomManager.cs | 5 +++++ .../Multi/Lounge/Components/RoomsContainer.cs | 16 ++++++++++++++++ osu.Game/Screens/Multi/RoomManager.cs | 13 +++++++++++-- 6 files changed, 44 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index e9dfb0f041..3e9f2fb3a4 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -71,6 +71,8 @@ namespace osu.Game.Tests.Visual private class TestRoomManager : IRoomManager { + public event Action RoomsUpdated; + public readonly BindableCollection Rooms = new BindableCollection(); IBindableCollection IRoomManager.Rooms => Rooms; diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index afce8999b4..7fb9d4dded 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -136,6 +136,8 @@ namespace osu.Game.Tests.Visual public Func CreateRequested; + public event Action RoomsUpdated; + public IBindableCollection Rooms { get; } = null; public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 0d6a8ae3a8..448f5ced91 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -79,6 +79,12 @@ namespace osu.Game.Online.Multiplayer set => MaxAttempts.Value = value; } + /// + /// The position of this in the list. This is not read from or written to the API. + /// + [JsonIgnore] + public int Position = -1; + public void CopyFrom(Room other) { RoomID.Value = other.RoomID; @@ -103,6 +109,8 @@ namespace osu.Game.Online.Multiplayer Playlist.AddRange(other.Playlist); else if (other.Playlist.Count > 0) Playlist.First().ID = other.Playlist.First().ID; + + Position = other.Position; } public bool ShouldSerializeRoomID() => false; diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index a929e1a0f7..f0dbcb0e71 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -10,6 +10,11 @@ namespace osu.Game.Screens.Multi { public interface IRoomManager { + /// + /// Invoked when the s have been updated. + /// + event Action RoomsUpdated; + /// /// All the active s. /// diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 33b71d1203..5133e96a52 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -52,6 +52,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components rooms.ItemsAdded += addRooms; rooms.ItemsRemoved += removeRooms; + roomManager.RoomsUpdated += updateSorting; + addRooms(rooms); } @@ -104,6 +106,12 @@ namespace osu.Game.Screens.Multi.Lounge.Components } } + private void updateSorting() + { + foreach (var room in roomFlow) + roomFlow.SetLayoutPosition(room, room.Room.Position); + } + private void selectRoom(Room room) { var drawable = roomFlow.FirstOrDefault(r => r.Room == room); @@ -115,5 +123,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components selectedRoom.Value = room; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (roomManager != null) + roomManager.RoomsUpdated -= updateSorting; + } } } diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 6fe2307d8b..96dbe79258 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -19,6 +19,8 @@ namespace osu.Game.Screens.Multi { public class RoomManager : PollingComponent, IRoomManager { + public event Action RoomsUpdated; + private readonly BindableCollection rooms = new BindableCollection(); public IBindableCollection Rooms => rooms; @@ -44,6 +46,7 @@ namespace osu.Game.Screens.Multi public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { room.Host.Value = api.LocalUser; + room.RoomID.Value = 100; var req = new CreateRoomRequest(room); @@ -52,6 +55,8 @@ namespace osu.Game.Screens.Multi update(room, result); addRoom(room); + RoomsUpdated?.Invoke(); + onSuccess?.Invoke(room); }; @@ -125,13 +130,17 @@ namespace osu.Game.Screens.Multi rooms.Remove(r); } - // Add new matches, or update existing - foreach (var r in result) + for (int i = 0; i < result.Count; i++) { + var r = result[i]; + r.Position = i; + update(r, r); addRoom(r); } + RoomsUpdated?.Invoke(); + tcs.SetResult(true); }; From 72482aff8d61cabd0427ed631f8e1d473a18ff86 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 28 Dec 2018 01:48:13 +0900 Subject: [PATCH 349/355] Whoops --- osu.Game/Screens/Multi/RoomManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 96dbe79258..fab19c3fd7 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -46,7 +46,6 @@ namespace osu.Game.Screens.Multi public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { room.Host.Value = api.LocalUser; - room.RoomID.Value = 100; var req = new CreateRoomRequest(room); From 55607634b4cebcd74c1130293222845923099525 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 28 Dec 2018 13:28:07 +0900 Subject: [PATCH 350/355] Fix covers being loaded even when off-screen --- .../UpdateableBeatmapBackgroundSprite.cs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 93783f757b..724c6d656a 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -25,23 +25,26 @@ namespace osu.Game.Beatmaps.Drawables protected override Drawable CreateDrawable(BeatmapInfo model) { - Drawable drawable; + return new DelayedLoadUnloadWrapper(() => { + Drawable drawable; - var localBeatmap = beatmaps.GetWorkingBeatmap(model); + var localBeatmap = beatmaps.GetWorkingBeatmap(model); - if (localBeatmap.BeatmapInfo.ID == 0 && model?.BeatmapSet?.OnlineInfo != null) - drawable = new BeatmapSetCover(model.BeatmapSet); - else - drawable = new BeatmapBackgroundSprite(localBeatmap); + if (localBeatmap.BeatmapInfo.ID == 0 && model?.BeatmapSet?.OnlineInfo != null) + drawable = new BeatmapSetCover(model.BeatmapSet); + else + drawable = new BeatmapBackgroundSprite(localBeatmap); - drawable.RelativeSizeAxes = Axes.Both; - drawable.Anchor = Anchor.Centre; - drawable.Origin = Anchor.Centre; - drawable.FillMode = FillMode.Fill; + drawable.RelativeSizeAxes = Axes.Both; + drawable.Anchor = Anchor.Centre; + drawable.Origin = Anchor.Centre; + drawable.FillMode = FillMode.Fill; + drawable.OnLoadComplete = d => d.FadeInFromZero(400); - return drawable; + return drawable; + }, 500, 10000); } - protected override double FadeDuration => 400; + protected override double FadeDuration => 0; } } From 0047f29ec8208bea117135bd9d28be414dc73813 Mon Sep 17 00:00:00 2001 From: FreezyLemon Date: Sun, 30 Dec 2018 22:40:17 +0100 Subject: [PATCH 351/355] move missing newline to front of "Plays with..." --- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 23739d8ad1..90f4e5851d 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -396,11 +396,11 @@ namespace osu.Game.Overlays.Profile infoTextLeft.NewLine(); infoTextLeft.AddText("Last seen ", lightText); infoTextLeft.AddText(new DrawableDate(user.LastVisit.Value), boldItalic); - infoTextLeft.NewParagraph(); } if (user.PlayStyle?.Length > 0) { + infoTextLeft.NewParagraph(); infoTextLeft.AddText("Plays with ", lightText); infoTextLeft.AddText(string.Join(", ", user.PlayStyle), boldItalic); } From 2d405bfc43b819c2ad73aed46c8ba68022f89e62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Jan 2019 16:33:52 +0900 Subject: [PATCH 352/355] Add back options for 3 and 7 day long rooms --- .../Screens/Multi/Match/Components/MatchSettingsOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 68c97d16eb..69ca4b1deb 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -165,8 +165,8 @@ namespace osu.Game.Screens.Multi.Match.Components TimeSpan.FromHours(12), //TimeSpan.FromHours(16), TimeSpan.FromHours(24), - //TimeSpan.FromDays(3), - //TimeSpan.FromDays(7) + TimeSpan.FromDays(3), + TimeSpan.FromDays(7) } } }, From c56d8b75c15d2c0a5f0145d18c3b7d1cf2286223 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jan 2019 17:43:10 +0900 Subject: [PATCH 353/355] Cache slider's endposition --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 26 ++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index d508ec2636..ffb7f7be9e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Rulesets.Objects; using System.Linq; +using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -26,8 +27,11 @@ namespace osu.Game.Rulesets.Osu.Objects public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; public double Duration => EndTime - StartTime; + private Cached endPositionCache; + + public override Vector2 EndPosition => endPositionCache.IsValid ? endPositionCache.Value : endPositionCache.Value = Position + this.CurvePositionAt(1); + public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t); - public override Vector2 EndPosition => Position + this.CurvePositionAt(1); public override int ComboIndex { @@ -56,7 +60,11 @@ namespace osu.Game.Rulesets.Osu.Objects public SliderPath Path { get => PathBindable.Value; - set => PathBindable.Value = value; + set + { + PathBindable.Value = value; + endPositionCache.Invalidate(); + } } public double Distance => Path.Distance; @@ -73,6 +81,8 @@ namespace osu.Game.Rulesets.Osu.Objects if (TailCircle != null) TailCircle.Position = EndPosition; + + endPositionCache.Invalidate(); } } @@ -92,7 +102,17 @@ namespace osu.Game.Rulesets.Osu.Objects public List> NodeSamples { get; set; } = new List>(); - public int RepeatCount { get; set; } + private int repeatCount; + + public int RepeatCount + { + get => repeatCount; + set + { + repeatCount = value; + endPositionCache.Invalidate(); + } + } /// /// The length of one span of this . From 273b14b19cc74a2feb60e0940f60a6f206f1e3e3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jan 2019 18:51:47 +0900 Subject: [PATCH 354/355] Add a maximum length for slider ticks to be generated --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index ffb7f7be9e..2d82f7aecf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -24,6 +24,12 @@ namespace osu.Game.Rulesets.Osu.Objects /// private const float base_scoring_distance = 100; + /// + /// A very lenient maximum length of a slider for ticks to be generated. + /// This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. + /// + private const double max_length_for_ticks = 100000; + public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; public double Duration => EndTime - StartTime; @@ -189,7 +195,7 @@ namespace osu.Game.Rulesets.Osu.Objects private void createTicks() { - var length = Path.Distance; + var length = Math.Min(max_length_for_ticks, Path.Distance); var tickDistance = MathHelper.Clamp(TickDistance, 0, length); if (tickDistance == 0) return; From 3fa5a33fb1edef5d18861c4dbb04928d6cf5252d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jan 2019 18:58:07 +0900 Subject: [PATCH 355/355] Inline const --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 2d82f7aecf..2af1de7355 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -24,12 +24,6 @@ namespace osu.Game.Rulesets.Osu.Objects /// private const float base_scoring_distance = 100; - /// - /// A very lenient maximum length of a slider for ticks to be generated. - /// This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. - /// - private const double max_length_for_ticks = 100000; - public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; public double Duration => EndTime - StartTime; @@ -195,7 +189,11 @@ namespace osu.Game.Rulesets.Osu.Objects private void createTicks() { - var length = Math.Min(max_length_for_ticks, Path.Distance); + // A very lenient maximum length of a slider for ticks to be generated. + // This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. + const double max_length = 100000; + + var length = Math.Min(max_length, Path.Distance); var tickDistance = MathHelper.Clamp(TickDistance, 0, length); if (tickDistance == 0) return;