From 06fe5583cb9ecd4915aad3835b09ae732dfc1aff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 28 Jul 2023 15:47:57 +0900 Subject: [PATCH 01/59] Expose a new SSDQ from playfield for skinnable area bounds --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 17 +++++++++++++++++ osu.Game/Rulesets/UI/Playfield.cs | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index e3ebadc836..7b00447238 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; @@ -25,6 +26,22 @@ namespace osu.Game.Rulesets.Mania.UI private readonly List stages = new List(); + public override Quad SkinnableComponentScreenSpaceDrawQuad + { + get + { + if (Stages.Count == 1) + return Stages.First().ScreenSpaceDrawQuad; + + RectangleF area = RectangleF.Empty; + + foreach (var stage in Stages) + area = RectangleF.Union(area, stage.ScreenSpaceDrawQuad.AABBFloat); + + return area; + } + } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos)); public ManiaPlayfield(List stageDefinitions) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 3f263aba63..e9c35555c8 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -23,6 +23,7 @@ using osu.Game.Skinning; using osuTK; using osu.Game.Rulesets.Objects.Pooling; using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.UI { @@ -94,6 +95,16 @@ namespace osu.Game.Rulesets.UI /// public readonly BindableBool DisplayJudgements = new BindableBool(true); + /// + /// A screen space draw quad which resembles the edges of the playfield for skinning purposes. + /// This will allow users / components to snap objects to the "edge" of the playfield. + /// + /// + /// Rulesets which reduce the visible area further than the full relative playfield space itself + /// should retarget this to the ScreenSpaceDrawQuad of the appropriate container. + /// + public virtual Quad SkinnableComponentScreenSpaceDrawQuad => ScreenSpaceDrawQuad; + [Resolved(CanBeNull = true)] [CanBeNull] protected IReadOnlyList Mods { get; private set; } From 5bd06832d0a4e35bbbd52eea2ffb3970764e6d0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 28 Jul 2023 15:48:40 +0900 Subject: [PATCH 02/59] Fix skin component toolbox not working correctly for ruleset matching Until now, the only usage of ruleset layers was where there is both a ruleset specific and non-ruleset-specific layer present. The matching code was making assumptions about this. As I tried to add a new playfield layer which breaks this assumption, non-ruleset-specifc components were not being displayed in the toolbox. This turned out to be due to a `target` of `null` being provided due to the weird `getTarget` matching (that happened to *just* do what we wanted previously due to the equals implementation, but only because there was a container without the ruleset present in the available targets). I've changed this to be a more appropriate lookup method, where the target for dependency sourcing is provided separately from the ruleset filter. --- .../Overlays/SkinEditor/SkinComponentToolbox.cs | 17 +++++++++++++---- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs b/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs index 1ce253d67c..a476fc1a6d 100644 --- a/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs +++ b/osu.Game/Overlays/SkinEditor/SkinComponentToolbox.cs @@ -13,6 +13,7 @@ using osu.Framework.Threading; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; +using osu.Game.Rulesets; using osu.Game.Screens.Edit.Components; using osu.Game.Skinning; using osuTK; @@ -23,14 +24,22 @@ namespace osu.Game.Overlays.SkinEditor { public Action? RequestPlacement; - private readonly SkinComponentsContainer? target; + private readonly SkinComponentsContainer target; + + private readonly RulesetInfo? ruleset; private FillFlowContainer fill = null!; - public SkinComponentToolbox(SkinComponentsContainer? target = null) - : base(target?.Lookup.Ruleset == null ? SkinEditorStrings.Components : LocalisableString.Interpolate($"{SkinEditorStrings.Components} ({target.Lookup.Ruleset.Name})")) + /// + /// Create a new component toolbox for the specified taget. + /// + /// The target. This is mainly used as a dependency source to find candidate components. + /// A ruleset to filter components by. If null, only components which are not ruleset-specific will be included. + public SkinComponentToolbox(SkinComponentsContainer target, RulesetInfo? ruleset) + : base(ruleset == null ? SkinEditorStrings.Components : LocalisableString.Interpolate($"{SkinEditorStrings.Components} ({ruleset.Name})")) { this.target = target; + this.ruleset = ruleset; } [BackgroundDependencyLoader] @@ -51,7 +60,7 @@ namespace osu.Game.Overlays.SkinEditor { fill.Clear(); - var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(target?.Lookup.Ruleset); + var skinnableTypes = SerialisedDrawableInfo.GetAllAvailableDrawables(ruleset); foreach (var type in skinnableTypes) attemptAddComponent(type); } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 2b23ce290f..67cf0eab18 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -366,14 +366,14 @@ namespace osu.Game.Overlays.SkinEditor // If the new target has a ruleset, let's show ruleset-specific items at the top, and the rest below. if (target.NewValue.Ruleset != null) { - componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer) + componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer, target.NewValue.Ruleset) { RequestPlacement = requestPlacement }); } // Remove the ruleset from the lookup to get base components. - componentsSidebar.Add(new SkinComponentToolbox(getTarget(new SkinComponentsContainerLookup(target.NewValue.Target))) + componentsSidebar.Add(new SkinComponentToolbox(skinComponentsContainer, null) { RequestPlacement = requestPlacement }); From 6cf065f6d1c92ddcdf36efa97fbe4634ee3cd9f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 28 Jul 2023 15:48:21 +0900 Subject: [PATCH 03/59] Add playfield layer to skin editor --- osu.Game/Screens/Play/HUDOverlay.cs | 14 ++++++++++++-- osu.Game/Skinning/SkinComponentsContainerLookup.cs | 5 ++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index d11171e3fe..6696332307 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -12,6 +12,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Configuration; @@ -103,10 +104,11 @@ namespace osu.Game.Screens.Play private readonly List hideTargets; + private readonly Drawable playfieldComponents; + public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList mods, bool alwaysShowLeaderboard = true) { Drawable rulesetComponents; - this.drawableRuleset = drawableRuleset; this.mods = mods; @@ -123,6 +125,9 @@ namespace osu.Game.Screens.Play rulesetComponents = drawableRuleset != null ? new HUDComponentsContainer(drawableRuleset.Ruleset.RulesetInfo) { AlwaysPresent = true, } : Empty(), + playfieldComponents = drawableRuleset != null + ? new SkinComponentsContainer(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.Playfield, drawableRuleset.Ruleset.RulesetInfo)) { AlwaysPresent = true, } + : Empty(), topRightElements = new FillFlowContainer { Anchor = Anchor.TopRight, @@ -162,7 +167,7 @@ namespace osu.Game.Screens.Play }, }; - hideTargets = new List { mainComponents, rulesetComponents, topRightElements }; + hideTargets = new List { mainComponents, rulesetComponents, playfieldComponents, topRightElements }; if (!alwaysShowLeaderboard) hideTargets.Add(LeaderboardFlow); @@ -230,6 +235,11 @@ namespace osu.Game.Screens.Play { base.Update(); + Quad playfieldScreenSpaceDrawQuad = drawableRuleset.Playfield.SkinnableComponentScreenSpaceDrawQuad; + + playfieldComponents.Position = ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); + playfieldComponents.Size = ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); + float? lowestTopScreenSpaceLeft = null; float? lowestTopScreenSpaceRight = null; diff --git a/osu.Game/Skinning/SkinComponentsContainerLookup.cs b/osu.Game/Skinning/SkinComponentsContainerLookup.cs index fbc0ab58ad..34358c3f06 100644 --- a/osu.Game/Skinning/SkinComponentsContainerLookup.cs +++ b/osu.Game/Skinning/SkinComponentsContainerLookup.cs @@ -68,7 +68,10 @@ namespace osu.Game.Skinning MainHUDComponents, [Description("Song select")] - SongSelect + SongSelect, + + [Description("Playfield")] + Playfield } } } From aca8310cd1df87a131e1e1dfc7d0bc047101c578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 28 Jul 2023 23:36:57 +0200 Subject: [PATCH 04/59] Fix non-compiling test To be fair, currently the test is a bit pointless (as it has no reason to be a `SkinnableTestScene`, it gains precisely nothing from it - all that is shown there is some generic components on song select). But that is no worse then `master`, so look away for now. --- .../Visual/Gameplay/TestSceneSkinEditorComponentsList.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs index 515bc09bbb..b7b2a6c175 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs @@ -8,6 +8,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.SkinEditor; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Skinning; namespace osu.Game.Tests.Visual.Gameplay { @@ -19,7 +20,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestToggleEditor() { - AddStep("show available components", () => SetContents(_ => new SkinComponentToolbox + var skinComponentsContainer = new SkinComponentsContainer(new SkinComponentsContainerLookup(SkinComponentsContainerLookup.TargetArea.SongSelect)); + + AddStep("show available components", () => SetContents(_ => new SkinComponentToolbox(skinComponentsContainer, null) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From 1fd4a6dc96fe5b87ee9c616a2518775a731a765e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 29 Jul 2023 01:07:08 +0200 Subject: [PATCH 05/59] Fix tests crashing due to `HUDOverlay` not finding `DrawableRuleset` in `Update()` --- osu.Game/Screens/Play/HUDOverlay.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 6696332307..536d3ac146 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -70,7 +70,9 @@ namespace osu.Game.Screens.Play public Bindable ShowHealthBar = new Bindable(true); + [CanBeNull] private readonly DrawableRuleset drawableRuleset; + private readonly IReadOnlyList mods; /// @@ -106,7 +108,7 @@ namespace osu.Game.Screens.Play private readonly Drawable playfieldComponents; - public HUDOverlay(DrawableRuleset drawableRuleset, IReadOnlyList mods, bool alwaysShowLeaderboard = true) + public HUDOverlay([CanBeNull] DrawableRuleset drawableRuleset, IReadOnlyList mods, bool alwaysShowLeaderboard = true) { Drawable rulesetComponents; this.drawableRuleset = drawableRuleset; @@ -235,10 +237,13 @@ namespace osu.Game.Screens.Play { base.Update(); - Quad playfieldScreenSpaceDrawQuad = drawableRuleset.Playfield.SkinnableComponentScreenSpaceDrawQuad; + if (drawableRuleset != null) + { + Quad playfieldScreenSpaceDrawQuad = drawableRuleset.Playfield.SkinnableComponentScreenSpaceDrawQuad; - playfieldComponents.Position = ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); - playfieldComponents.Size = ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); + playfieldComponents.Position = ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); + playfieldComponents.Size = ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); + } float? lowestTopScreenSpaceLeft = null; float? lowestTopScreenSpaceRight = null; From a3301dc7ffb0a6e4958065f8b8210a3b98c1fdc4 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 28 Jul 2023 23:22:28 -0700 Subject: [PATCH 06/59] Fix accuracy break info decimal separator being incorrect in certain languages --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 7261155c94..b8696352e8 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Play.Break private void currentValueChanged(ValueChangedEvent e) { - string newText = prefix + Format(e.NewValue); + LocalisableString newText = LocalisableString.Interpolate($"{prefix}{Format(e.NewValue)}"); if (valueText.Text == newText) return; From 8a06914438fd3d1d8bdcc462c5fe196891bee2c7 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 25 Jul 2023 20:50:55 +0900 Subject: [PATCH 07/59] remove #nullable disable in tournament --- .../NonVisual/LadderInfoSerialisationTest.cs | 5 +- .../Screens/TestSceneLadderEditorScreen.cs | 2 +- .../Screens/TestSceneSeedingEditorScreen.cs | 3 +- .../Screens/TestSceneTeamIntroScreen.cs | 2 +- .../Screens/TestSceneTeamWinScreen.cs | 2 +- .../TournamentTestScene.cs | 9 +-- .../Components/DrawableTeamFlag.cs | 10 ++- .../Components/DrawableTeamTitle.cs | 8 +-- .../Components/DrawableTournamentTeam.cs | 11 ++-- osu.Game.Tournament/Components/SongBar.cs | 8 +-- .../Components/TournamentBeatmapPanel.cs | 18 +++-- .../Components/TournamentMatchChatDisplay.cs | 4 +- .../Components/TourneyVideo.cs | 6 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 65 +++++++++---------- osu.Game.Tournament/JsonPointConverter.cs | 9 +-- osu.Game.Tournament/Models/LadderInfo.cs | 6 +- osu.Game.Tournament/Models/RoundBeatmap.cs | 1 - osu.Game.Tournament/Models/StableInfo.cs | 6 +- osu.Game.Tournament/Models/TournamentMatch.cs | 22 +++---- osu.Game.Tournament/Models/TournamentTeam.cs | 9 ++- .../Screens/Drawings/Components/Group.cs | 4 +- .../Components/ScrollingTeamContainer.cs | 27 ++++---- .../Components/StorageBackedTeamList.cs | 6 +- .../Components/VisualiserContainer.cs | 4 +- .../Screens/Drawings/DrawingsScreen.cs | 28 ++++---- .../Screens/Editors/LadderEditorScreen.cs | 64 ++++++++---------- .../Gameplay/Components/MatchHeader.cs | 8 +-- .../Gameplay/Components/TeamDisplay.cs | 2 +- .../Gameplay/Components/TeamScoreDisplay.cs | 24 ++++--- .../Components/TournamentMatchScoreDisplay.cs | 4 +- .../Screens/Gameplay/GameplayScreen.cs | 36 +++++----- .../Ladder/Components/DrawableMatchTeam.cs | 29 ++++----- .../Components/DrawableTournamentMatch.cs | 28 ++++---- .../Components/DrawableTournamentRound.cs | 4 +- .../Ladder/Components/LadderEditorSettings.cs | 22 +++---- .../Ladder/Components/SettingsTeamDropdown.cs | 2 +- .../Screens/Ladder/LadderScreen.cs | 12 ++-- .../Screens/MapPool/MapPoolScreen.cs | 38 ++++++----- .../Screens/Schedule/ScheduleScreen.cs | 10 ++- .../Screens/Setup/ResolutionSelector.cs | 6 +- .../Screens/Setup/SetupScreen.cs | 22 +++---- .../Screens/Setup/StablePathSelectScreen.cs | 12 ++-- .../Screens/Setup/TournamentSwitcher.cs | 10 ++- .../Screens/Showcase/ShowcaseScreen.cs | 2 +- .../Screens/TeamIntro/SeedingScreen.cs | 22 +++---- .../Screens/TeamIntro/TeamIntroScreen.cs | 6 +- .../Screens/TeamWin/TeamWinScreen.cs | 12 ++-- .../Screens/TournamentMatchScreen.cs | 8 +-- osu.Game.Tournament/TournamentGame.cs | 8 +-- osu.Game.Tournament/TournamentGameBase.cs | 29 +++++---- osu.Game.Tournament/TournamentSceneManager.cs | 20 +++--- 51 files changed, 333 insertions(+), 382 deletions(-) diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs index 962a6fbd6c..d18651b8bb 100644 --- a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json; using NUnit.Framework; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.NonVisual @@ -35,8 +36,8 @@ namespace osu.Game.Tournament.Tests.NonVisual PlayersPerTeam = { Value = 4 }, Teams = { - match.Team1.Value, - match.Team2.Value, + match.Team1.Value.AsNonNull(), + match.Team2.Value.AsNonNull(), }, Rounds = { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index 29ecdaf873..b9b150d264 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tournament.Tests.Screens AddStep("release mouse button", () => InputManager.ReleaseButton(MouseButton.Left)); - AddAssert("assert ladder teams reset", () => Ladder.CurrentMatch.Value.Team1.Value == null && Ladder.CurrentMatch.Value.Team2.Value == null); + AddAssert("assert ladder teams reset", () => Ladder.CurrentMatch.Value?.Team1.Value == null && Ladder.CurrentMatch.Value?.Team2.Value == null); } } } diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs index 15d4fb1f3f..a7ef4d7a29 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Editors; @@ -17,7 +18,7 @@ namespace osu.Game.Tournament.Tests.Screens { var match = CreateSampleMatch(); - Add(new SeedingEditorScreen(match.Team1.Value, new TeamEditorScreen()) + Add(new SeedingEditorScreen(match.Team1.Value.AsNonNull(), new TeamEditorScreen()) { Width = 0.85f // create room for control panel }); diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index b76e0d7521..d6941848b7 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens { Team1 = { Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA") }, Team2 = { Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN") }, - Round = { Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals") } + Round = { Value = Ladder.Rounds.First(g => g.Name.Value == "Quarterfinals") } }; Add(new TeamIntroScreen diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index 05c21fa0b1..1e3ff72d43 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tournament.Tests.Screens { var match = Ladder.CurrentMatch.Value!; - match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); + match.Round.Value = Ladder.Rounds.First(g => g.Name.Value == "Quarterfinals"); match.Completed.Value = true; }); diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 84e5da62f4..0cf1e22211 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; @@ -40,10 +41,10 @@ namespace osu.Game.Tournament.Tests match = CreateSampleMatch(); - Ladder.Rounds.Add(match.Round.Value); + Ladder.Rounds.Add(match.Round.Value.AsNonNull()); Ladder.Matches.Add(match); - Ladder.Teams.Add(match.Team1.Value); - Ladder.Teams.Add(match.Team2.Value); + Ladder.Teams.Add(match.Team1.Value.AsNonNull()); + Ladder.Teams.Add(match.Team2.Value.AsNonNull()); Ruleset.BindTo(Ladder.Ruleset); Dependencies.CacheAs(new StableInfo(storage)); @@ -152,7 +153,7 @@ namespace osu.Game.Tournament.Tests }, Round = { - Value = new TournamentRound { Name = { Value = "Quarterfinals" } } + Value = new TournamentRound { Name = { Value = "Quarterfinals" } }, } }; diff --git a/osu.Game.Tournament/Components/DrawableTeamFlag.cs b/osu.Game.Tournament/Components/DrawableTeamFlag.cs index 317d685ee7..aef854bb8d 100644 --- a/osu.Game.Tournament/Components/DrawableTeamFlag.cs +++ b/osu.Game.Tournament/Components/DrawableTeamFlag.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -17,14 +15,14 @@ namespace osu.Game.Tournament.Components { public partial class DrawableTeamFlag : Container { - private readonly TournamentTeam team; + private readonly TournamentTeam? team; [UsedImplicitly] - private Bindable flag; + private Bindable? flag; - private Sprite flagSprite; + private Sprite? flagSprite; - public DrawableTeamFlag(TournamentTeam team) + public DrawableTeamFlag(TournamentTeam? team) { this.team = team; } diff --git a/osu.Game.Tournament/Components/DrawableTeamTitle.cs b/osu.Game.Tournament/Components/DrawableTeamTitle.cs index 68cc46be19..85b3e5419c 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitle.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitle.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -12,12 +10,12 @@ namespace osu.Game.Tournament.Components { public partial class DrawableTeamTitle : TournamentSpriteTextWithBackground { - private readonly TournamentTeam team; + private readonly TournamentTeam? team; [UsedImplicitly] - private Bindable acronym; + private Bindable? acronym; - public DrawableTeamTitle(TournamentTeam team) + public DrawableTeamTitle(TournamentTeam? team) { this.team = team; } diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index 0036f5f115..9583682e8b 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -14,15 +12,15 @@ namespace osu.Game.Tournament.Components { public abstract partial class DrawableTournamentTeam : CompositeDrawable { - public readonly TournamentTeam Team; + public readonly TournamentTeam? Team; protected readonly Container Flag; protected readonly TournamentSpriteText AcronymText; [UsedImplicitly] - private Bindable acronym; + private Bindable? acronym; - protected DrawableTournamentTeam(TournamentTeam team) + protected DrawableTournamentTeam(TournamentTeam? team) { Team = team; @@ -36,7 +34,8 @@ namespace osu.Game.Tournament.Components [BackgroundDependencyLoader] private void load() { - if (Team == null) return; + if (Team == null) + return; (acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(_ => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true); } diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 4f4a02ccf1..19d63286d8 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -24,12 +22,12 @@ namespace osu.Game.Tournament.Components { public partial class SongBar : CompositeDrawable { - private TournamentBeatmap beatmap; + private TournamentBeatmap? beatmap; public const float HEIGHT = 145 / 2f; [Resolved] - private IBindable ruleset { get; set; } + private IBindable ruleset { get; set; } = null!; public TournamentBeatmap Beatmap { @@ -55,7 +53,7 @@ namespace osu.Game.Tournament.Components } } - private FillFlowContainer flow; + private FillFlowContainer flow = null!; private bool expanded; diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 49478a2174..2d5844d02b 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -22,13 +22,13 @@ namespace osu.Game.Tournament.Components { public readonly TournamentBeatmap? Beatmap; - private readonly string mod; + private readonly string? mod; public const float HEIGHT = 50; private readonly Bindable currentMatch = new Bindable(); - private Box flash = null!; + private Box? flash; public TournamentBeatmapPanel(TournamentBeatmap? beatmap, string mod = "") { @@ -135,25 +135,29 @@ namespace osu.Game.Tournament.Components match.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged; if (match.NewValue != null) match.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged; - - Scheduler.AddOnce(updateState); + updateState(); } private void picksBansOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - => Scheduler.AddOnce(updateState); + => updateState(); private BeatmapChoice? choice; private void updateState() { - var newChoice = currentMatch.Value?.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap?.OnlineID); + if (currentMatch.Value == null) + { + return; + } + + var newChoice = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap?.OnlineID); bool shouldFlash = newChoice != choice; if (newChoice != null) { if (shouldFlash) - flash.FadeOutFromOne(500).Loop(0, 10); + flash?.FadeOutFromOne(500).Loop(0, 10); BorderThickness = 6; diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index e943cb8b8c..0998e606e9 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -92,9 +92,9 @@ namespace osu.Game.Tournament.Components { if (info.CurrentMatch.Value is TournamentMatch match) { - if (match.Team1.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) + if (match.Team1.Value?.Players.Any(u => u.OnlineID == Message.Sender.OnlineID) == true) UsernameColour = TournamentGame.COLOUR_RED; - else if (match.Team2.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) + else if (match.Team2.Value?.Players.Any(u => u.OnlineID == Message.Sender.OnlineID) == true) UsernameColour = TournamentGame.COLOUR_BLUE; } } diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index b9ce84b735..6e45c7556b 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -19,8 +17,8 @@ namespace osu.Game.Tournament.Components { private readonly string filename; private readonly bool drawFallbackGradient; - private Video video; - private ManualClock manualClock; + private Video? video; + private ManualClock? manualClock; public bool VideoAvailable => video != null; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 7babb3ea5a..333dd0fd73 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.IO; using System.Linq; -using JetBrains.Annotations; using Microsoft.Win32; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; @@ -24,36 +21,35 @@ namespace osu.Game.Tournament.IPC { public partial class FileBasedIPC : MatchIPCInfo { - public Storage IPCStorage { get; private set; } + public Storage? IPCStorage { get; private set; } [Resolved] - protected IAPIProvider API { get; private set; } + protected IAPIProvider API { get; private set; } = null!; [Resolved] - protected IRulesetStore Rulesets { get; private set; } + protected IRulesetStore Rulesets { get; private set; } = null!; [Resolved] - private GameHost host { get; set; } + private GameHost host { get; set; } = null!; [Resolved] - private LadderInfo ladder { get; set; } + private LadderInfo ladder { get; set; } = null!; [Resolved] - private StableInfo stableInfo { get; set; } + private StableInfo stableInfo { get; set; } = null!; private int lastBeatmapId; - private ScheduledDelegate scheduled; - private GetBeatmapRequest beatmapLookupRequest; + private ScheduledDelegate? scheduled; + private GetBeatmapRequest? beatmapLookupRequest; [BackgroundDependencyLoader] private void load() { - string stablePath = stableInfo.StablePath ?? findStablePath(); + string? stablePath = stableInfo.StablePath ?? findStablePath(); initialiseIPCStorage(stablePath); } - [CanBeNull] - private Storage initialiseIPCStorage(string path) + private Storage? initialiseIPCStorage(string? path) { scheduled?.Cancel(); @@ -89,9 +85,9 @@ namespace osu.Game.Tournament.IPC lastBeatmapId = beatmapId; - var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.Beatmap != null); + var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId); - if (existing != null) + if (existing?.Beatmap != null) Beatmap.Value = existing.Beatmap; else { @@ -114,7 +110,7 @@ namespace osu.Game.Tournament.IPC using (var stream = IPCStorage.GetStream(file_ipc_channel_filename)) using (var sr = new StreamReader(stream)) { - ChatChannel.Value = sr.ReadLine(); + ChatChannel.Value = sr.ReadLine().AsNonNull(); } } catch (Exception) @@ -140,8 +136,8 @@ namespace osu.Game.Tournament.IPC using (var stream = IPCStorage.GetStream(file_ipc_scores_filename)) using (var sr = new StreamReader(stream)) { - Score1.Value = int.Parse(sr.ReadLine()); - Score2.Value = int.Parse(sr.ReadLine()); + Score1.Value = int.Parse(sr.ReadLine().AsNonNull()); + Score2.Value = int.Parse(sr.ReadLine().AsNonNull()); } } catch (Exception) @@ -164,7 +160,7 @@ namespace osu.Game.Tournament.IPC /// /// Path to the IPC directory /// Whether the supplied path was a valid IPC directory. - public bool SetIPCLocation(string path) + public bool SetIPCLocation(string? path) { if (path == null || !ipcFileExistsInDirectory(path)) return false; @@ -184,29 +180,28 @@ namespace osu.Game.Tournament.IPC /// Whether an IPC directory was successfully auto-detected. public bool AutoDetectIPCLocation() => SetIPCLocation(findStablePath()); - private static bool ipcFileExistsInDirectory(string p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); + private static bool ipcFileExistsInDirectory(string? p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); - [CanBeNull] - private string findStablePath() + private string? findStablePath() { - string stableInstallPath = findFromEnvVar() ?? - findFromRegistry() ?? - findFromLocalAppData() ?? - findFromDotFolder(); + string? stableInstallPath = findFromEnvVar() ?? + findFromRegistry() ?? + findFromLocalAppData() ?? + findFromDotFolder(); Logger.Log($"Stable path for tourney usage: {stableInstallPath}"); return stableInstallPath; } - private string findFromEnvVar() + private string? findFromEnvVar() { try { Logger.Log("Trying to find stable with environment variables"); - string stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); + string? stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); if (ipcFileExistsInDirectory(stableInstallPath)) - return stableInstallPath; + return stableInstallPath!; } catch { @@ -215,7 +210,7 @@ namespace osu.Game.Tournament.IPC return null; } - private string findFromLocalAppData() + private string? findFromLocalAppData() { Logger.Log("Trying to find stable in %LOCALAPPDATA%"); string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); @@ -226,7 +221,7 @@ namespace osu.Game.Tournament.IPC return null; } - private string findFromDotFolder() + private string? findFromDotFolder() { Logger.Log("Trying to find stable in dotfolders"); string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu"); @@ -237,16 +232,16 @@ namespace osu.Game.Tournament.IPC return null; } - private string findFromRegistry() + private string? findFromRegistry() { Logger.Log("Trying to find stable in registry"); try { - string stableInstallPath; + string? stableInstallPath; #pragma warning disable CA1416 - using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) + using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu")) stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); #pragma warning restore CA1416 diff --git a/osu.Game.Tournament/JsonPointConverter.cs b/osu.Game.Tournament/JsonPointConverter.cs index d3b40a3526..a58ec47612 100644 --- a/osu.Game.Tournament/JsonPointConverter.cs +++ b/osu.Game.Tournament/JsonPointConverter.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Diagnostics; using System.Drawing; @@ -28,7 +26,7 @@ namespace osu.Game.Tournament if (reader.TokenType != JsonToken.StartObject) { // if there's no object present then this is using string representation (System.Drawing.Point serializes to "x,y") - string str = (string)reader.Value; + string? str = (string?)reader.Value; Debug.Assert(str != null); @@ -45,9 +43,12 @@ namespace osu.Game.Tournament if (reader.TokenType == JsonToken.PropertyName) { - string name = reader.Value?.ToString(); + string? name = reader.Value?.ToString(); int? val = reader.ReadAsInt32(); + if (name == null) + continue; + if (val == null) continue; diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 229837c94e..219a2a7bfb 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -17,7 +15,7 @@ namespace osu.Game.Tournament.Models [Serializable] public class LadderInfo { - public Bindable Ruleset = new Bindable(); + public Bindable Ruleset = new Bindable(); public BindableList Matches = new BindableList(); public BindableList Rounds = new BindableList(); @@ -27,7 +25,7 @@ namespace osu.Game.Tournament.Models public List Progressions = new List(); [JsonIgnore] // updated manually in TournamentGameBase - public Bindable CurrentMatch = new Bindable(); + public Bindable CurrentMatch = new Bindable(); public Bindable ChromaKeyWidth = new BindableInt(1024) { diff --git a/osu.Game.Tournament/Models/RoundBeatmap.cs b/osu.Game.Tournament/Models/RoundBeatmap.cs index f2ec261246..b03b28b3b8 100644 --- a/osu.Game.Tournament/Models/RoundBeatmap.cs +++ b/osu.Game.Tournament/Models/RoundBeatmap.cs @@ -8,7 +8,6 @@ namespace osu.Game.Tournament.Models public class RoundBeatmap { public int ID; - public string Mods = string.Empty; [JsonProperty("BeatmapInfo")] diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index 1ae80d4596..7ee0b4a361 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.IO; using Newtonsoft.Json; @@ -20,12 +18,12 @@ namespace osu.Game.Tournament.Models /// /// Path to the IPC directory used by the stable (cutting-edge) install. /// - public string StablePath { get; set; } + public string? StablePath { get; set; } /// /// Fired whenever stable info is successfully saved to file. /// - public event Action OnStableInfoSaved; + public event Action? OnStableInfoSaved; private const string config_path = "stable.json"; diff --git a/osu.Game.Tournament/Models/TournamentMatch.cs b/osu.Game.Tournament/Models/TournamentMatch.cs index 97c2060f2c..0a700eb4d6 100644 --- a/osu.Game.Tournament/Models/TournamentMatch.cs +++ b/osu.Game.Tournament/Models/TournamentMatch.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -33,16 +31,16 @@ namespace osu.Game.Tournament.Models } [JsonIgnore] - public readonly Bindable Team1 = new Bindable(); + public readonly Bindable Team1 = new Bindable(); - public string Team1Acronym; + public string? Team1Acronym; public readonly Bindable Team1Score = new Bindable(); [JsonIgnore] - public readonly Bindable Team2 = new Bindable(); + public readonly Bindable Team2 = new Bindable(); - public string Team2Acronym; + public string? Team2Acronym; public readonly Bindable Team2Score = new Bindable(); @@ -53,13 +51,13 @@ namespace osu.Game.Tournament.Models public readonly ObservableCollection PicksBans = new ObservableCollection(); [JsonIgnore] - public readonly Bindable Round = new Bindable(); + public readonly Bindable Round = new Bindable(); [JsonIgnore] - public readonly Bindable Progression = new Bindable(); + public readonly Bindable Progression = new Bindable(); [JsonIgnore] - public readonly Bindable LosersProgression = new Bindable(); + public readonly Bindable LosersProgression = new Bindable(); /// /// Should not be set directly. Use LadderInfo.CurrentMatch.Value = this instead. @@ -79,7 +77,7 @@ namespace osu.Game.Tournament.Models Team2.BindValueChanged(t => Team2Acronym = t.NewValue?.Acronym.Value, true); } - public TournamentMatch(TournamentTeam team1 = null, TournamentTeam team2 = null) + public TournamentMatch(TournamentTeam? team1 = null, TournamentTeam? team2 = null) : this() { Team1.Value = team1; @@ -87,10 +85,10 @@ namespace osu.Game.Tournament.Models } [JsonIgnore] - public TournamentTeam Winner => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value; + public TournamentTeam? Winner => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value; [JsonIgnore] - public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; + public TournamentTeam? Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value; public TeamColour WinnerColour => Winner == Team1.Value ? TeamColour.Red : TeamColour.Blue; diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index 1beea517d5..3587aa937e 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; namespace osu.Game.Tournament.Models { @@ -39,7 +38,7 @@ namespace osu.Game.Tournament.Models { int[] ranks = Players.Select(p => p.Rank) .Where(i => i.HasValue) - .Select(i => i.Value) + .Select(i => i.AsNonNull().Value) .ToArray(); if (ranks.Length == 0) @@ -66,14 +65,14 @@ namespace osu.Game.Tournament.Models { // use a sane default flag name based on acronym. if (val.OldValue.StartsWith(FlagName.Value, StringComparison.InvariantCultureIgnoreCase)) - FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpperInvariant() : string.Empty; + FlagName.Value = val.NewValue?.Length >= 2 ? val.NewValue.Substring(0, 2).ToUpperInvariant() : string.Empty; }; FullName.ValueChanged += val => { // use a sane acronym based on full name. if (val.OldValue.StartsWith(Acronym.Value, StringComparison.InvariantCultureIgnoreCase)) - Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpperInvariant() : string.Empty; + Acronym.Value = val.NewValue?.Length >= 3 ? val.NewValue.Substring(0, 3).ToUpperInvariant() : string.Empty; }; } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index a79e2253a4..9d4474a58c 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -84,7 +84,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components public bool ContainsTeam(string fullName) { - return allTeams.Any(t => t.Team.FullName.Value == fullName); + return allTeams.Any(t => t.Team?.FullName.Value == fullName); } public bool RemoveTeam(TournamentTeam team) @@ -112,7 +112,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { StringBuilder sb = new StringBuilder(); foreach (GroupTeam gt in allTeams) - sb.AppendLine(gt.Team.FullName.Value); + sb.AppendLine(gt.Team?.FullName.Value); return sb.ToString(); } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index c2b15dd3e9..4a47de8714 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -22,8 +21,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { public partial class ScrollingTeamContainer : Container { - public event Action OnScrollStarted; - public event Action OnSelected; + public event Action? OnScrollStarted; + public event Action? OnSelected; private readonly List availableTeams = new List(); @@ -42,7 +41,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components private double lastTime; - private ScheduledDelegate delayedStateChangeDelegate; + private ScheduledDelegate? delayedStateChangeDelegate; public ScrollingTeamContainer() { @@ -117,7 +116,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components if (!Children.Any()) break; - ScrollingTeam closest = null; + ScrollingTeam? closest = null; foreach (var c in Children) { @@ -139,15 +138,14 @@ namespace osu.Game.Tournament.Screens.Drawings.Components Trace.Assert(closest != null, "closest != null"); - // ReSharper disable once PossibleNullReferenceException - offset += DrawWidth / 2f - (closest.Position.X + closest.DrawWidth / 2f); + offset += DrawWidth / 2f - (closest.AsNonNull().Position.X + closest.AsNonNull().DrawWidth / 2f); - ScrollingTeam st = closest; + ScrollingTeam st = closest.AsNonNull(); availableTeams.RemoveAll(at => at == st.Team); st.Selected = true; - OnSelected?.Invoke(st.Team); + OnSelected?.Invoke(st.Team.AsNonNull()); delayedStateChangeDelegate = Scheduler.AddDelayed(() => setScrollState(ScrollState.Idle), 10000); break; @@ -174,7 +172,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components setScrollState(ScrollState.Idle); } - public void AddTeams(IEnumerable teams) + public void AddTeams(IEnumerable? teams) { if (teams == null) return; @@ -190,8 +188,11 @@ namespace osu.Game.Tournament.Screens.Drawings.Components setScrollState(ScrollState.Idle); } - public void RemoveTeam(TournamentTeam team) + public void RemoveTeam(TournamentTeam? team) { + if (team == null) + return; + availableTeams.Remove(team); foreach (var c in Children) @@ -311,6 +312,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components public partial class ScrollingTeam : DrawableTournamentTeam { + public new TournamentTeam Team => base.Team.AsNonNull(); + public const float WIDTH = 58; public const float HEIGHT = 44; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index 74afb42c1a..e13462b9bd 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -39,7 +37,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { while (sr.Peek() != -1) { - string line = sr.ReadLine()?.Trim(); + string? line = sr.ReadLine()?.Trim(); if (string.IsNullOrEmpty(line)) continue; @@ -56,7 +54,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components teams.Add(new TournamentTeam { FullName = { Value = split[1], }, - Acronym = { Value = split.Length >= 3 ? split[2] : null, }, + Acronym = { Value = split.Length >= 3 ? split[2] : string.Empty, }, FlagName = { Value = split[0] } }); } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs index 676eec14cd..d5e39e3f44 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -72,7 +70,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components private float leftPos => -(float)((Time.Current + Offset) / CycleTime) + expiredCount; - private Texture texture; + private Texture texture = null!; private int expiredCount; diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 23d0edf26e..b2dd4e8c36 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -1,14 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -28,27 +27,27 @@ namespace osu.Game.Tournament.Screens.Drawings { private const string results_filename = "drawings_results.txt"; - private ScrollingTeamContainer teamsContainer; - private GroupContainer groupsContainer; - private TournamentSpriteText fullTeamNameText; + private ScrollingTeamContainer teamsContainer = null!; + private GroupContainer groupsContainer = null!; + private TournamentSpriteText fullTeamNameText = null!; private readonly List allTeams = new List(); - private DrawingsConfigManager drawingsConfig; + private DrawingsConfigManager drawingsConfig = null!; - private Task writeOp; + private Task? writeOp; - private Storage storage; + private Storage storage = null!; - public ITeamList TeamList; + public ITeamList? TeamList; [BackgroundDependencyLoader] private void load(Storage storage) { - RelativeSizeAxes = Axes.Both; - this.storage = storage; + RelativeSizeAxes = Axes.Both; + TeamList ??= new StorageBackedTeamList(storage); if (!TeamList.Teams.Any()) @@ -224,7 +223,7 @@ namespace osu.Game.Tournament.Screens.Drawings teamsContainer.ClearTeams(); allTeams.Clear(); - foreach (TournamentTeam t in TeamList.Teams) + foreach (TournamentTeam t in TeamList.AsNonNull().Teams) { if (groupsContainer.ContainsTeam(t.FullName.Value)) continue; @@ -251,7 +250,7 @@ namespace osu.Game.Tournament.Screens.Drawings using (Stream stream = storage.GetStream(results_filename, FileAccess.Read, FileMode.Open)) using (StreamReader sr = new StreamReader(stream)) { - string line; + string? line; while ((line = sr.ReadLine()?.Trim()) != null) { @@ -261,8 +260,7 @@ namespace osu.Game.Tournament.Screens.Drawings if (line.ToUpperInvariant().StartsWith("GROUP", StringComparison.Ordinal)) continue; - // ReSharper disable once AccessToModifiedClosure - TournamentTeam teamToAdd = allTeams.FirstOrDefault(t => t.FullName.Value == line); + TournamentTeam? teamToAdd = allTeams.FirstOrDefault(t => t.FullName.Value == line); if (teamToAdd == null) continue; diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index 9411892dc5..a82ac57ee9 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Drawing; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,13 +32,12 @@ namespace osu.Game.Tournament.Screens.Editors [Cached] private LadderEditorInfo editorInfo = new LadderEditorInfo(); - private WarningBox rightClickMessage; + private WarningBox rightClickMessage = null!; - private RectangularPositionSnapGrid grid; + private RectangularPositionSnapGrid grid = null!; [Resolved(canBeNull: true)] - [CanBeNull] - private IDialogOverlay dialogOverlay { get; set; } + private IDialogOverlay? dialogOverlay { get; set; } protected override bool DrawLoserPaths => true; @@ -94,36 +90,28 @@ namespace osu.Game.Tournament.Screens.Editors ScrollContent.Add(new JoinVisualiser(MatchesContainer, match, losers, UpdateLayout)); } - public MenuItem[] ContextMenuItems - { - get + public MenuItem[] ContextMenuItems => + new MenuItem[] { - if (editorInfo == null) - return Array.Empty(); - - return new MenuItem[] + new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => { - new OsuMenuItem("Create new match", MenuItemType.Highlighted, () => + Vector2 pos = MatchesContainer.Count == 0 ? Vector2.Zero : lastMatchesContainerMouseDownPosition; + + TournamentMatch newMatch = new TournamentMatch { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }; + + LadderInfo.Matches.Add(newMatch); + + editorInfo.Selected.Value = newMatch; + }), + new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => + { + dialogOverlay?.Push(new LadderResetTeamsDialog(() => { - Vector2 pos = MatchesContainer.Count == 0 ? Vector2.Zero : lastMatchesContainerMouseDownPosition; - - TournamentMatch newMatch = new TournamentMatch { Position = { Value = new Point((int)pos.X, (int)pos.Y) } }; - - LadderInfo.Matches.Add(newMatch); - - editorInfo.Selected.Value = newMatch; - }), - new OsuMenuItem("Reset teams", MenuItemType.Destructive, () => - { - dialogOverlay?.Push(new LadderResetTeamsDialog(() => - { - foreach (var p in MatchesContainer) - p.Match.Reset(); - })); - }) - }; - } - } + foreach (var p in MatchesContainer) + p.Match.Reset(); + })); + }) + }; public void Remove(TournamentMatch match) { @@ -135,11 +123,11 @@ namespace osu.Game.Tournament.Screens.Editors private readonly Container matchesContainer; public readonly TournamentMatch Source; private readonly bool losers; - private readonly Action complete; + private readonly Action? complete; - private ProgressionPath path; + private ProgressionPath? path; - public JoinVisualiser(Container matchesContainer, TournamentMatch source, bool losers, Action complete) + public JoinVisualiser(Container matchesContainer, TournamentMatch source, bool losers, Action? complete) { this.matchesContainer = matchesContainer; RelativeSizeAxes = Axes.Both; @@ -153,7 +141,7 @@ namespace osu.Game.Tournament.Screens.Editors Source.Progression.Value = null; } - private DrawableTournamentMatch findTarget(InputState state) + private DrawableTournamentMatch? findTarget(InputState state) { return matchesContainer.FirstOrDefault(d => d.ReceivePositionalInputAt(state.Mouse.Position)); } diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 8f7484980d..69f150c8ac 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,9 +12,9 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { public partial class MatchHeader : Container { - private TeamScoreDisplay teamDisplay1; - private TeamScoreDisplay teamDisplay2; - private DrawableTournamentHeaderLogo logo; + private TeamScoreDisplay teamDisplay1 = null!; + private TeamScoreDisplay teamDisplay2 = null!; + private DrawableTournamentHeaderLogo logo = null!; private bool showScores = true; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs index c23327a43f..3fdbbb5973 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components } } - public TeamDisplay(TournamentTeam team, TeamColour colour, Bindable currentTeamScore, int pointsToWin) + public TeamDisplay(TournamentTeam? team, TeamColour colour, Bindable currentTeamScore, int pointsToWin) : base(team) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs index 57fe1c7312..c7fcfae602 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -17,16 +15,22 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { private readonly TeamColour teamColour; - private readonly Bindable currentMatch = new Bindable(); - private readonly Bindable currentTeam = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentTeam = new Bindable(); private readonly Bindable currentTeamScore = new Bindable(); - private TeamDisplay teamDisplay; + private TeamDisplay? teamDisplay; public bool ShowScore { - get => teamDisplay.ShowScore; - set => teamDisplay.ShowScore = value; + get => teamDisplay?.ShowScore ?? false; + set + { + if (teamDisplay != null) + { + teamDisplay.ShowScore = value; + } + } } public TeamScoreDisplay(TeamColour teamColour) @@ -48,7 +52,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components updateMatch(); } - private void matchChanged(ValueChangedEvent match) + private void matchChanged(ValueChangedEvent match) { currentTeamScore.UnbindBindings(); currentTeam.UnbindBindings(); @@ -78,7 +82,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components switch (e.Button) { case MouseButton.Left: - if (currentTeamScore.Value < currentMatch.Value.PointsToWin) + if (currentTeamScore.Value < currentMatch.Value?.PointsToWin) currentTeamScore.Value++; return true; @@ -91,7 +95,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components return base.OnMouseDown(e); } - private void teamChanged(ValueChangedEvent team) + private void teamChanged(ValueChangedEvent team) { bool wasShowingScores = teamDisplay?.ShowScore ?? false; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index 838e5fa071..7ae20acc77 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -146,7 +144,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components private partial class MatchScoreCounter : CommaSeparatedScoreCounter { - private OsuSpriteText displayedSpriteText; + private OsuSpriteText displayedSpriteText = null!; public MatchScoreCounter() { diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 4258522cff..79c50e60ba 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -26,16 +24,16 @@ namespace osu.Game.Tournament.Screens.Gameplay private readonly BindableBool warmup = new BindableBool(); public readonly Bindable State = new Bindable(); - private OsuButton warmupButton; - private MatchIPCInfo ipc; + private OsuButton warmupButton = null!; + private MatchIPCInfo ipc = null!; [Resolved(canBeNull: true)] - private TournamentSceneManager sceneManager { get; set; } + private TournamentSceneManager? sceneManager { get; set; } [Resolved] - private TournamentMatchChatDisplay chat { get; set; } + private TournamentMatchChatDisplay chat { get; set; } = null!; - private Drawable chroma; + private Drawable chroma = null!; [BackgroundDependencyLoader] private void load(LadderInfo ladder, MatchIPCInfo ipc) @@ -142,7 +140,7 @@ namespace osu.Game.Tournament.Screens.Gameplay State.BindValueChanged(_ => updateState(), true); } - protected override void CurrentMatchChanged(ValueChangedEvent match) + protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); @@ -153,29 +151,35 @@ namespace osu.Game.Tournament.Screens.Gameplay scheduledScreenChange?.Cancel(); } - private ScheduledDelegate scheduledScreenChange; - private ScheduledDelegate scheduledContract; + private ScheduledDelegate? scheduledScreenChange; + private ScheduledDelegate? scheduledContract; - private TournamentMatchScoreDisplay scoreDisplay; + private TournamentMatchScoreDisplay scoreDisplay = null!; private TourneyState lastState; - private MatchHeader header; + private MatchHeader header = null!; private void contract() { + if (!IsLoaded) + return; + scheduledContract?.Cancel(); SongBar.Expanded = false; scoreDisplay.FadeOut(100); - using (chat?.BeginDelayedSequence(500)) - chat?.Expand(); + using (chat.BeginDelayedSequence(500)) + chat.Expand(); } private void expand() { + if (!IsLoaded) + return; + scheduledContract?.Cancel(); - chat?.Contract(); + chat.Contract(); using (BeginDelayedSequence(300)) { @@ -252,7 +256,7 @@ namespace osu.Game.Tournament.Screens.Gameplay private partial class ChromaArea : CompositeDrawable { [Resolved] - private LadderInfo ladder { get; set; } + private LadderInfo ladder { get; set; } = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index 2b66df1a31..a380ad9b49 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -28,20 +26,20 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { private readonly TournamentMatch match; private readonly bool losers; - private TournamentSpriteText scoreText; - private Box background; - private Box backgroundRight; + private TournamentSpriteText scoreText = null!; + private Box background = null!; + private Box backgroundRight = null!; private readonly Bindable score = new Bindable(); private readonly BindableBool completed = new BindableBool(); private Color4 colourWinner; - private readonly Func isWinner; - private LadderEditorScreen ladderEditor; + private readonly Func? isWinner; + private LadderEditorScreen ladderEditor = null!; [Resolved(canBeNull: true)] - private LadderInfo ladderInfo { get; set; } + private LadderInfo? ladderInfo { get; set; } private void setCurrent() { @@ -56,9 +54,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } [Resolved(CanBeNull = true)] - private LadderEditorInfo editorInfo { get; set; } + private LadderEditorInfo? editorInfo { get; set; } - public DrawableMatchTeam(TournamentTeam team, TournamentMatch match, bool losers) + public DrawableMatchTeam(TournamentTeam? team, TournamentMatch match, bool losers) : base(team) { this.match = match; @@ -72,14 +70,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components AcronymText.Padding = new MarginPadding { Left = 50 }; AcronymText.Font = OsuFont.Torus.With(size: 22, weight: FontWeight.Bold); - if (match != null) - { - isWinner = () => match.Winner == Team; + isWinner = () => match.Winner == Team; - completed.BindTo(match.Completed); - if (team != null) - score.BindTo(team == match.Team1.Value ? match.Team1Score : match.Team2Score); - } + completed.BindTo(match.Completed); + if (team != null) + score.BindTo(team == match.Team1.Value ? match.Team1Score : match.Team2Score); } [BackgroundDependencyLoader(true)] diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs index c394877ae9..7b8f2e373b 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -27,13 +26,13 @@ namespace osu.Game.Tournament.Screens.Ladder.Components protected readonly FillFlowContainer Flow; private readonly Drawable selectionBox; private readonly Drawable currentMatchSelectionBox; - private Bindable globalSelection; + private Bindable? globalSelection; [Resolved(CanBeNull = true)] - private LadderEditorInfo editorInfo { get; set; } + private LadderEditorInfo? editorInfo { get; set; } [Resolved(CanBeNull = true)] - private LadderInfo ladderInfo { get; set; } + private LadderInfo? ladderInfo { get; set; } public DrawableTournamentMatch(TournamentMatch match, bool editor = false) { @@ -129,7 +128,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components /// /// Fired when something changed that requires a ladder redraw. /// - public Action Changed; + public Action? Changed; private readonly List refBindables = new List(); @@ -201,20 +200,22 @@ namespace osu.Game.Tournament.Screens.Ladder.Components } else { - transferProgression(Match.Progression?.Value, Match.Winner); - transferProgression(Match.LosersProgression?.Value, Match.Loser); + Debug.Assert(Match.Winner != null); + transferProgression(Match.Progression.Value, Match.Winner); + Debug.Assert(Match.Loser != null); + transferProgression(Match.LosersProgression.Value, Match.Loser); } Changed?.Invoke(); } - private void transferProgression(TournamentMatch destination, TournamentTeam team) + private void transferProgression(TournamentMatch? destination, TournamentTeam team) { if (destination == null) return; bool progressionAbove = destination.ID < Match.ID; - Bindable destinationTeam; + Bindable destinationTeam; // check for the case where we have already transferred out value if (destination.Team1.Value == team) @@ -268,8 +269,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { foreach (var conditional in Match.ConditionalMatches) { - bool team1Match = conditional.Acronyms.Contains(Match.Team1Acronym); - bool team2Match = conditional.Acronyms.Contains(Match.Team2Acronym); + bool team1Match = Match.Team1Acronym != null && conditional.Acronyms.Contains(Match.Team1Acronym); + bool team2Match = Match.Team2Acronym != null && conditional.Acronyms.Contains(Match.Team2Acronym); if (team1Match && team2Match) Match.Date.Value = conditional.Date.Value; @@ -344,6 +345,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components Match.Progression.Value = null; Match.LosersProgression.Value = null; + if (ladderInfo == null) + return; + ladderInfo.Matches.Remove(Match); foreach (var m in ladderInfo.Matches) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs index 4b2a29247b..216e0a5a3e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -52,7 +50,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components name.BindValueChanged(_ => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpperInvariant(), true); description = round.Description.GetBoundCopy(); - description.BindValueChanged(_ => textDescription.Text = round.Description.Value?.ToUpperInvariant(), true); + description.BindValueChanged(_ => textDescription.Text = round.Description.Value?.ToUpperInvariant() ?? string.Empty, true); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index 5c9c14cc30..9f0fa19915 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; @@ -23,17 +21,17 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { public partial class LadderEditorSettings : CompositeDrawable { - private SettingsDropdown roundDropdown; - private PlayerCheckbox losersCheckbox; - private DateTextBox dateTimeBox; - private SettingsTeamDropdown team1Dropdown; - private SettingsTeamDropdown team2Dropdown; + private SettingsDropdown roundDropdown = null!; + private PlayerCheckbox losersCheckbox = null!; + private DateTextBox dateTimeBox = null!; + private SettingsTeamDropdown team1Dropdown = null!; + private SettingsTeamDropdown team2Dropdown = null!; [Resolved] - private LadderEditorInfo editorInfo { get; set; } + private LadderEditorInfo editorInfo { get; set; } = null!; [Resolved] - private LadderInfo ladderInfo { get; set; } + private LadderInfo ladderInfo { get; set; } = null!; [BackgroundDependencyLoader] private void load() @@ -77,7 +75,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }; } - private void roundDropdownChanged(ValueChangedEvent round) + private void roundDropdownChanged(ValueChangedEvent round) { if (editorInfo.Selected.Value?.Date.Value < round.NewValue?.StartDate.Value) { @@ -101,11 +99,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { } - private partial class SettingsRoundDropdown : SettingsDropdown + private partial class SettingsRoundDropdown : SettingsDropdown { public SettingsRoundDropdown(BindableList rounds) { - Current = new Bindable(); + Current = new Bindable(); foreach (var r in rounds.Prepend(new TournamentRound())) add(r); diff --git a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs index 00e5353edd..7e35190e2e 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs @@ -12,7 +12,7 @@ using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components { - public partial class SettingsTeamDropdown : SettingsDropdown + public partial class SettingsTeamDropdown : SettingsDropdown { public SettingsTeamDropdown(BindableList teams) { diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 2d5281b893..4f56a2fcc9 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -22,13 +20,13 @@ namespace osu.Game.Tournament.Screens.Ladder { public partial class LadderScreen : TournamentScreen { - protected Container MatchesContainer; - private Container paths; - private Container headings; + protected Container MatchesContainer = null!; + private Container paths = null!; + private Container headings = null!; - protected LadderDragContainer ScrollContent; + protected LadderDragContainer ScrollContent = null!; - protected Container Content; + protected Container Content = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index f45da861cb..3091f4293c 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -24,20 +22,20 @@ namespace osu.Game.Tournament.Screens.MapPool { public partial class MapPoolScreen : TournamentMatchScreen { - private FillFlowContainer> mapFlows; + private FillFlowContainer> mapFlows = null!; [Resolved(canBeNull: true)] - private TournamentSceneManager sceneManager { get; set; } + private TournamentSceneManager? sceneManager { get; set; } private TeamColour pickColour; private ChoiceType pickType; - private OsuButton buttonRedBan; - private OsuButton buttonBlueBan; - private OsuButton buttonRedPick; - private OsuButton buttonBluePick; + private OsuButton buttonRedBan = null!; + private OsuButton buttonBlueBan = null!; + private OsuButton buttonRedPick = null!; + private OsuButton buttonBluePick = null!; - private ScheduledDelegate scheduledScreenChange; + private ScheduledDelegate? scheduledScreenChange; [BackgroundDependencyLoader] private void load(MatchIPCInfo ipc) @@ -113,7 +111,7 @@ namespace osu.Game.Tournament.Screens.MapPool ipc.Beatmap.BindValueChanged(beatmapChanged); } - private Bindable splitMapPoolByMods; + private Bindable? splitMapPoolByMods; protected override void LoadComplete() { @@ -148,6 +146,9 @@ namespace osu.Game.Tournament.Screens.MapPool private void setNextMode() { + if (CurrentMatch.Value == null) + return; + const TeamColour roll_winner = TeamColour.Red; //todo: draw from match var nextColour = (CurrentMatch.Value.PicksBans.LastOrDefault()?.Team ?? roll_winner) == TeamColour.Red ? TeamColour.Blue : TeamColour.Red; @@ -169,11 +170,11 @@ namespace osu.Game.Tournament.Screens.MapPool addForBeatmap(map.Beatmap.OnlineID); else { - var existing = CurrentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap?.OnlineID); + var existing = CurrentMatch.Value?.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap?.OnlineID); if (existing != null) { - CurrentMatch.Value.PicksBans.Remove(existing); + CurrentMatch.Value?.PicksBans.Remove(existing); setNextMode(); } } @@ -186,13 +187,13 @@ namespace osu.Game.Tournament.Screens.MapPool private void reset() { - CurrentMatch.Value.PicksBans.Clear(); + CurrentMatch.Value?.PicksBans.Clear(); setNextMode(); } private void addForBeatmap(int beatmapId) { - if (CurrentMatch.Value == null) + if (CurrentMatch.Value?.Round.Value == null) return; if (CurrentMatch.Value.Round.Value.Beatmaps.All(b => b.Beatmap?.OnlineID != beatmapId)) @@ -228,7 +229,7 @@ namespace osu.Game.Tournament.Screens.MapPool base.Hide(); } - protected override void CurrentMatchChanged(ValueChangedEvent match) + protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); updateDisplay(); @@ -245,12 +246,15 @@ namespace osu.Game.Tournament.Screens.MapPool if (CurrentMatch.Value.Round.Value != null) { - FillFlowContainer currentFlow = null; - string currentMods = null; + FillFlowContainer? currentFlow = null; + string? currentMods = null; int flowCount = 0; foreach (var b in CurrentMatch.Value.Round.Value.Beatmaps) { + if (b.Beatmap == null) + continue; + if (currentFlow == null || (LadderInfo.SplitMapPoolByMods.Value && currentMods != b.Mods)) { mapFlows.Add(currentFlow = new FillFlowContainer diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 9232b4c689..063c231add 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -21,9 +19,9 @@ namespace osu.Game.Tournament.Screens.Schedule { public partial class ScheduleScreen : TournamentScreen { - private readonly Bindable currentMatch = new Bindable(); - private Container mainContainer; - private LadderInfo ladder; + private readonly Bindable currentMatch = new Bindable(); + private Container mainContainer = null!; + private LadderInfo ladder = null!; [BackgroundDependencyLoader] private void load(LadderInfo ladder) @@ -107,7 +105,7 @@ namespace osu.Game.Tournament.Screens.Schedule currentMatch.BindValueChanged(matchChanged, true); } - private void matchChanged(ValueChangedEvent match) + private void matchChanged(ValueChangedEvent match) { var upcoming = ladder.Matches.Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4); var conditionals = ladder diff --git a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs index e6ab6f143a..c700e3bfdd 100644 --- a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs +++ b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -14,9 +12,9 @@ namespace osu.Game.Tournament.Screens.Setup private const int minimum_window_height = 480; private const int maximum_window_height = 2160; - public new Action Action; + public new Action? Action; - private OsuNumberBox numberBox; + private OsuNumberBox? numberBox; protected override Drawable CreateComponent() { diff --git a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs index 5c7bbed69c..1152759c2a 100644 --- a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Drawing; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -24,27 +22,27 @@ namespace osu.Game.Tournament.Screens.Setup { public partial class SetupScreen : TournamentScreen { - private FillFlowContainer fillFlow; + private FillFlowContainer fillFlow = null!; - private LoginOverlay loginOverlay; - private ResolutionSelector resolution; + private LoginOverlay? loginOverlay; + private ResolutionSelector resolution = null!; [Resolved] - private MatchIPCInfo ipc { get; set; } + private MatchIPCInfo ipc { get; set; } = null!; [Resolved] - private StableInfo stableInfo { get; set; } + private StableInfo stableInfo { get; set; } = null!; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; [Resolved] - private RulesetStore rulesets { get; set; } + private RulesetStore rulesets { get; set; } = null!; [Resolved(canBeNull: true)] - private TournamentSceneManager sceneManager { get; set; } + private TournamentSceneManager? sceneManager { get; set; } - private Bindable windowSize; + private Bindable windowSize = null!; [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) @@ -115,7 +113,7 @@ namespace osu.Game.Tournament.Screens.Setup Failing = api.IsLoggedIn != true, Description = "In order to access the API and display metadata, signing in is required." }, - new LabelledDropdown + new LabelledDropdown { Label = "Ruleset", Description = "Decides what stats are displayed and which ranks are retrieved for players. This requires a restart to reload data for an existing bracket.", diff --git a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs index 463b012b77..c3d072b6a0 100644 --- a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -24,19 +22,19 @@ namespace osu.Game.Tournament.Screens.Setup public partial class StablePathSelectScreen : TournamentScreen { [Resolved(canBeNull: true)] - private TournamentSceneManager sceneManager { get; set; } + private TournamentSceneManager? sceneManager { get; set; } [Resolved] - private MatchIPCInfo ipc { get; set; } + private MatchIPCInfo ipc { get; set; } = null!; - private OsuDirectorySelector directorySelector; - private DialogOverlay overlay; + private OsuDirectorySelector directorySelector = null!; + private DialogOverlay? overlay; [BackgroundDependencyLoader(true)] private void load(Storage storage, OsuColour colours) { var initialStorage = (ipc as FileBasedIPC)?.IPCStorage ?? storage; - string initialPath = new DirectoryInfo(initialStorage.GetFullPath(string.Empty)).Parent?.FullName; + string? initialPath = new DirectoryInfo(initialStorage.GetFullPath(string.Empty)).Parent?.FullName; AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index ae49ccb63b..e55cbc2dbb 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -13,12 +11,12 @@ namespace osu.Game.Tournament.Screens.Setup { internal partial class TournamentSwitcher : ActionableInfo { - private OsuDropdown dropdown; - private OsuButton folderButton; - private OsuButton reloadTournamentsButton; + private OsuDropdown dropdown = null!; + private OsuButton folderButton = null!; + private OsuButton reloadTournamentsButton = null!; [Resolved] - private TournamentGameBase game { get; set; } + private TournamentGameBase game { get; set; } = null!; [BackgroundDependencyLoader] private void load(TournamentStorage storage) diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index db4d6198e6..ae2ec0c291 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Showcase }); } - protected override void CurrentMatchChanged(ValueChangedEvent match) + protected override void CurrentMatchChanged(ValueChangedEvent match) { // showcase screen doesn't care about a match being selected. // base call intentionally omitted to not show match warning. diff --git a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs index b07a0a65dd..120a76c127 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -22,12 +20,12 @@ namespace osu.Game.Tournament.Screens.TeamIntro { public partial class SeedingScreen : TournamentMatchScreen { - private Container mainContainer; + private Container mainContainer = null!; - private readonly Bindable currentTeam = new Bindable(); + private readonly Bindable currentTeam = new Bindable(); - private TourneyButton showFirstTeamButton; - private TourneyButton showSecondTeamButton; + private TourneyButton showFirstTeamButton = null!; + private TourneyButton showSecondTeamButton = null!; [BackgroundDependencyLoader] private void load() @@ -53,13 +51,13 @@ namespace osu.Game.Tournament.Screens.TeamIntro { RelativeSizeAxes = Axes.X, Text = "Show first team", - Action = () => currentTeam.Value = CurrentMatch.Value.Team1.Value, + Action = () => currentTeam.Value = CurrentMatch.Value?.Team1.Value, }, showSecondTeamButton = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Show second team", - Action = () => currentTeam.Value = CurrentMatch.Value.Team2.Value, + Action = () => currentTeam.Value = CurrentMatch.Value?.Team2.Value, }, new SettingsTeamDropdown(LadderInfo.Teams) { @@ -73,7 +71,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro currentTeam.BindValueChanged(teamChanged, true); } - private void teamChanged(ValueChangedEvent team) => updateTeamDisplay(); + private void teamChanged(ValueChangedEvent team) => updateTeamDisplay(); public override void Show() { @@ -84,7 +82,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro updateTeamDisplay(); } - protected override void CurrentMatchChanged(ValueChangedEvent match) + protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); @@ -256,7 +254,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private partial class LeftInfo : CompositeDrawable { - public LeftInfo(TournamentTeam team) + public LeftInfo(TournamentTeam? team) { FillFlowContainer fill; @@ -315,7 +313,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro private partial class TeamDisplay : DrawableTournamentTeam { - public TeamDisplay(TournamentTeam team) + public TeamDisplay(TournamentTeam? team) : base(team) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index 950a63808c..2280f21d47 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -15,7 +13,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro { public partial class TeamIntroScreen : TournamentMatchScreen { - private Container mainContainer; + private Container mainContainer = null!; [BackgroundDependencyLoader] private void load() @@ -36,7 +34,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro }; } - protected override void CurrentMatchChanged(ValueChangedEvent match) + protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 9206de1dc2..af21613541 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,12 +14,12 @@ namespace osu.Game.Tournament.Screens.TeamWin { public partial class TeamWinScreen : TournamentMatchScreen { - private Container mainContainer; + private Container mainContainer = null!; private readonly Bindable currentCompleted = new Bindable(); - private TourneyVideo blueWinVideo; - private TourneyVideo redWinVideo; + private TourneyVideo blueWinVideo = null!; + private TourneyVideo redWinVideo = null!; [BackgroundDependencyLoader] private void load() @@ -51,7 +49,7 @@ namespace osu.Game.Tournament.Screens.TeamWin currentCompleted.BindValueChanged(_ => update()); } - protected override void CurrentMatchChanged(ValueChangedEvent match) + protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); @@ -70,7 +68,7 @@ namespace osu.Game.Tournament.Screens.TeamWin { var match = CurrentMatch.Value; - if (match.Winner == null) + if (match?.Winner == null) { mainContainer.Clear(); return; diff --git a/osu.Game.Tournament/Screens/TournamentMatchScreen.cs b/osu.Game.Tournament/Screens/TournamentMatchScreen.cs index 58444d0c1b..5a9b9d05ed 100644 --- a/osu.Game.Tournament/Screens/TournamentMatchScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentMatchScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Tournament.Models; @@ -10,8 +8,8 @@ namespace osu.Game.Tournament.Screens { public abstract partial class TournamentMatchScreen : TournamentScreen { - protected readonly Bindable CurrentMatch = new Bindable(); - private WarningBox noMatchWarning; + protected readonly Bindable CurrentMatch = new Bindable(); + private WarningBox? noMatchWarning; protected override void LoadComplete() { @@ -21,7 +19,7 @@ namespace osu.Game.Tournament.Screens CurrentMatch.BindValueChanged(CurrentMatchChanged, true); } - protected virtual void CurrentMatchChanged(ValueChangedEvent match) + protected virtual void CurrentMatchChanged(ValueChangedEvent match) { if (match.NewValue == null) { diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index c79cc9cd57..ba3b17b513 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Drawing; using System.Linq; using osu.Framework.Allocation; @@ -35,12 +33,12 @@ namespace osu.Game.Tournament public static readonly Color4 ELEMENT_FOREGROUND_COLOUR = Color4Extensions.FromHex("#000"); public static readonly Color4 TEXT_COLOUR = Color4Extensions.FromHex("#fff"); - private Drawable heightWarning; + private Drawable heightWarning = null!; - private Bindable windowMode; + private Bindable windowMode = null!; private readonly BindableSize windowSize = new BindableSize(); - private LoadingSpinner loadingSpinner; + private LoadingSpinner loadingSpinner = null!; [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 509c8bb940..ee03b4c35d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,14 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.IO; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.Input; @@ -31,11 +30,11 @@ namespace osu.Game.Tournament public partial class TournamentGameBase : OsuGameBase { public const string BRACKET_FILENAME = @"bracket.json"; - private LadderInfo ladder; - private TournamentStorage storage; - private DependencyContainer dependencies; - private FileBasedIPC ipc; - private BeatmapLookupCache beatmapCache; + private LadderInfo ladder = null!; + private TournamentStorage storage = null!; + private DependencyContainer dependencies = null!; + private FileBasedIPC ipc = null!; + private BeatmapLookupCache beatmapCache = null!; protected Task BracketLoadTask => bracketLoadTaskCompletionSource.Task; @@ -54,7 +53,7 @@ namespace osu.Game.Tournament return new ProductionEndpointConfiguration(); } - private TournamentSpriteText initialisationText; + private TournamentSpriteText initialisationText = null!; [BackgroundDependencyLoader] private void load(Storage baseStorage) @@ -78,6 +77,8 @@ namespace osu.Game.Tournament dependencies.CacheAs(new StableInfo(storage)); beatmapCache = dependencies.Get(); + + ladder = new LadderInfo(); } protected override void LoadComplete() @@ -100,11 +101,11 @@ namespace osu.Game.Tournament { using (Stream stream = storage.GetStream(BRACKET_FILENAME, FileAccess.Read, FileMode.Open)) using (var sr = new StreamReader(stream)) - ladder = JsonConvert.DeserializeObject(await sr.ReadToEndAsync().ConfigureAwait(false), new JsonPointConverter()); + { + ladder = JsonConvert.DeserializeObject(await sr.ReadToEndAsync().ConfigureAwait(false), new JsonPointConverter()) ?? ladder; + } } - ladder ??= new LadderInfo(); - var resolvedRuleset = ladder.Ruleset.Value != null ? RulesetStore.GetRuleset(ladder.Ruleset.Value.ShortName) : RulesetStore.AvailableRulesets.First(); @@ -283,7 +284,7 @@ namespace osu.Game.Tournament private void updateLoadProgressMessage(string s) => Schedule(() => initialisationText.Text = s); - public void PopulatePlayer(TournamentUser user, Action success = null, Action failure = null, bool immediate = false) + public void PopulatePlayer(TournamentUser user, Action? success = null, Action? failure = null, bool immediate = false) { var req = new GetUserRequest(user.OnlineID, ladder.Ruleset.Value); @@ -348,8 +349,8 @@ namespace osu.Game.Tournament foreach (var r in ladder.Rounds) r.Matches = ladder.Matches.Where(p => p.Round.Value == r).Select(p => p.ID).ToList(); - ladder.Progressions = ladder.Matches.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( - ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + ladder.Progressions = ladder.Matches.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.AsNonNull().ID)).Concat( + ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.AsNonNull().ID, true))) .ToList(); return JsonConvert.SerializeObject(ladder, diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 9ac5a9de12..c69b76ae29 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -35,8 +33,8 @@ namespace osu.Game.Tournament [Cached] public partial class TournamentSceneManager : CompositeDrawable { - private Container screens; - private TourneyVideo video; + private Container screens = null!; + private TourneyVideo video = null!; public const int CONTROL_AREA_WIDTH = 200; @@ -50,8 +48,8 @@ namespace osu.Game.Tournament [Cached] private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); - private Container chatContainer; - private FillFlowContainer buttons; + private Container chatContainer = null!; + private FillFlowContainer buttons = null!; public TournamentSceneManager() { @@ -166,10 +164,10 @@ namespace osu.Game.Tournament private float depth; - private Drawable currentScreen; - private ScheduledDelegate scheduledHide; + private Drawable? currentScreen; + private ScheduledDelegate? scheduledHide; - private Drawable temporaryScreen; + private Drawable? temporaryScreen; public void SetScreen(Drawable screen) { @@ -284,7 +282,7 @@ namespace osu.Game.Tournament Y = -2, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = shortcutKey.ToString(), + Text = shortcutKey.Value.ToString(), } } }); @@ -304,7 +302,7 @@ namespace osu.Game.Tournament private bool isSelected; - public Action RequestSelection; + public Action? RequestSelection; public bool IsSelected { From 4c33013674a9f2ddd761d966e1c6e08e88de66a6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 29 Jul 2023 22:41:26 +0900 Subject: [PATCH 08/59] null check in test --- .../Screens/TestSceneMapPoolScreen.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 2c17cd0d52..254d5c6996 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -1,11 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Tournament.Components; @@ -16,7 +15,7 @@ namespace osu.Game.Tournament.Tests.Screens { public partial class TestSceneMapPoolScreen : TournamentScreenTestScene { - private MapPoolScreen screen; + private MapPoolScreen screen = null!; [BackgroundDependencyLoader] private void load() @@ -32,7 +31,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load few maps", () => { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); for (int i = 0; i < 8; i++) addBeatmap(); @@ -52,7 +51,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load just enough maps", () => { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); for (int i = 0; i < 18; i++) addBeatmap(); @@ -72,7 +71,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); for (int i = 0; i < 19; i++) addBeatmap(); @@ -92,7 +91,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); for (int i = 0; i < 11; i++) addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); @@ -118,7 +117,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); for (int i = 0; i < 12; i++) addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); @@ -138,7 +137,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); for (int i = 0; i < 12; i++) addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); @@ -155,7 +154,7 @@ namespace osu.Game.Tournament.Tests.Screens private void addBeatmap(string mods = "NM") { - Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Add(new RoundBeatmap + Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Add(new RoundBeatmap { Beatmap = CreateSampleBeatmap(), Mods = mods From 033c9091c04377869a13185230fb4e95bf62c665 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 01:39:31 +0900 Subject: [PATCH 09/59] use cast instead AsNonNull --- osu.Game.Tournament/Models/TournamentTeam.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index 3587aa937e..b3b2f213ce 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tournament.Models { int[] ranks = Players.Select(p => p.Rank) .Where(i => i.HasValue) - .Select(i => i.AsNonNull().Value) + .Cast() .ToArray(); if (ranks.Length == 0) From 625ed729eed3a76703fe0c1713fa9617baf5e33b Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 01:39:56 +0900 Subject: [PATCH 10/59] debug assert `closest != null` --- .../Screens/Drawings/Components/ScrollingTeamContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index 4a47de8714..7f19e8a497 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -136,11 +136,11 @@ namespace osu.Game.Tournament.Screens.Drawings.Components closest = stc; } - Trace.Assert(closest != null, "closest != null"); + Debug.Assert(closest != null, "closest != null"); - offset += DrawWidth / 2f - (closest.AsNonNull().Position.X + closest.AsNonNull().DrawWidth / 2f); + offset += DrawWidth / 2f - (closest.Position.X + closest.DrawWidth / 2f); - ScrollingTeam st = closest.AsNonNull(); + ScrollingTeam st = closest; availableTeams.RemoveAll(at => at == st.Team); From cb4adf115cae1dbef79f1b8af64d0d71c768b537 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 01:40:13 +0900 Subject: [PATCH 11/59] RemoveTeam shouldn't have nullable arg --- .../Screens/Drawings/Components/ScrollingTeamContainer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index 7f19e8a497..d4e0f29852 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -188,11 +188,8 @@ namespace osu.Game.Tournament.Screens.Drawings.Components setScrollState(ScrollState.Idle); } - public void RemoveTeam(TournamentTeam? team) + public void RemoveTeam(TournamentTeam team) { - if (team == null) - return; - availableTeams.Remove(team); foreach (var c in Children) From 9482f7445614907f001aee2097939d25ad6c0b92 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 01:49:57 +0900 Subject: [PATCH 12/59] fix nullable for TeamList --- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index b2dd4e8c36..fc59b486fe 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tournament.Screens.Drawings private Storage storage = null!; - public ITeamList? TeamList; + public ITeamList TeamList = null!; [BackgroundDependencyLoader] private void load(Storage storage) @@ -48,7 +48,8 @@ namespace osu.Game.Tournament.Screens.Drawings RelativeSizeAxes = Axes.Both; - TeamList ??= new StorageBackedTeamList(storage); + if (TeamList.IsNull()) + TeamList = new StorageBackedTeamList(storage); if (!TeamList.Teams.Any()) { @@ -223,7 +224,7 @@ namespace osu.Game.Tournament.Screens.Drawings teamsContainer.ClearTeams(); allTeams.Clear(); - foreach (TournamentTeam t in TeamList.AsNonNull().Teams) + foreach (TournamentTeam t in TeamList.Teams) { if (groupsContainer.ContainsTeam(t.FullName.Value)) continue; From 88a1cf40052a92f70f8055fd1da33b44d575f022 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 01:57:44 +0900 Subject: [PATCH 13/59] remove all `canBeNull` from attribute --- osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs | 2 +- osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs | 2 +- .../Screens/Ladder/Components/DrawableMatchTeam.cs | 4 ++-- .../Screens/Ladder/Components/DrawableTournamentMatch.cs | 4 ++-- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 2 +- osu.Game.Tournament/Screens/Setup/SetupScreen.cs | 2 +- osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index a82ac57ee9..4074e681f9 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -36,7 +36,7 @@ namespace osu.Game.Tournament.Screens.Editors private RectangularPositionSnapGrid grid = null!; - [Resolved(canBeNull: true)] + [Resolved] private IDialogOverlay? dialogOverlay { get; set; } protected override bool DrawLoserPaths => true; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index 79c50e60ba..20188cc5dc 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tournament.Screens.Gameplay private OsuButton warmupButton = null!; private MatchIPCInfo ipc = null!; - [Resolved(canBeNull: true)] + [Resolved] private TournamentSceneManager? sceneManager { get; set; } [Resolved] diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index a380ad9b49..637591c6f6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private readonly Func? isWinner; private LadderEditorScreen ladderEditor = null!; - [Resolved(canBeNull: true)] + [Resolved] private LadderInfo? ladderInfo { get; set; } private void setCurrent() @@ -53,7 +53,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components ladderInfo.CurrentMatch.Value.Current.Value = true; } - [Resolved(CanBeNull = true)] + [Resolved] private LadderEditorInfo? editorInfo { get; set; } public DrawableMatchTeam(TournamentTeam? team, TournamentMatch match, bool losers) diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs index 7b8f2e373b..4de47d7c7f 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs @@ -28,10 +28,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components private readonly Drawable currentMatchSelectionBox; private Bindable? globalSelection; - [Resolved(CanBeNull = true)] + [Resolved] private LadderEditorInfo? editorInfo { get; set; } - [Resolved(CanBeNull = true)] + [Resolved] private LadderInfo? ladderInfo { get; set; } public DrawableTournamentMatch(TournamentMatch match, bool editor = false) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 3091f4293c..cfce2694e9 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tournament.Screens.MapPool { private FillFlowContainer> mapFlows = null!; - [Resolved(canBeNull: true)] + [Resolved] private TournamentSceneManager? sceneManager { get; set; } private TeamColour pickColour; diff --git a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs index 1152759c2a..df1ce69c33 100644 --- a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tournament.Screens.Setup [Resolved] private RulesetStore rulesets { get; set; } = null!; - [Resolved(canBeNull: true)] + [Resolved] private TournamentSceneManager? sceneManager { get; set; } private Bindable windowSize = null!; diff --git a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs index c3d072b6a0..74404e06f8 100644 --- a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Screens.Setup { public partial class StablePathSelectScreen : TournamentScreen { - [Resolved(canBeNull: true)] + [Resolved] private TournamentSceneManager? sceneManager { get; set; } [Resolved] From 9d928c0225d3b86257f1cf8cd71a606c46038892 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 29 Jul 2023 10:39:50 -0700 Subject: [PATCH 14/59] Apply NRT to `BreakInfoLine` --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index b8696352e8..c6a0ca0ef6 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -71,7 +69,7 @@ namespace osu.Game.Screens.Play.Break if (count is Enum countEnum) return countEnum.GetDescription(); - return count.ToString(); + return count.ToString() ?? string.Empty; } [BackgroundDependencyLoader] From 740898dffb910d5d6e8306c746e9578b383b47d0 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 29 Jul 2023 10:40:18 -0700 Subject: [PATCH 15/59] Remove unnecessary prefix parameter --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index c6a0ca0ef6..cfdf6cc651 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -24,12 +24,8 @@ namespace osu.Game.Screens.Play.Break private readonly OsuSpriteText text; private readonly OsuSpriteText valueText; - private readonly string prefix; - - public BreakInfoLine(LocalisableString name, string prefix = @"") + public BreakInfoLine(LocalisableString name) { - this.prefix = prefix; - AutoSizeAxes = Axes.Y; Children = new Drawable[] { @@ -45,7 +41,7 @@ namespace osu.Game.Screens.Play.Break { Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, - Text = prefix + @"-", + Text = @"-", Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = margin } } @@ -56,7 +52,7 @@ namespace osu.Game.Screens.Play.Break private void currentValueChanged(ValueChangedEvent e) { - LocalisableString newText = LocalisableString.Interpolate($"{prefix}{Format(e.NewValue)}"); + LocalisableString newText = Format(e.NewValue); if (valueText.Text == newText) return; @@ -82,8 +78,8 @@ namespace osu.Game.Screens.Play.Break public partial class PercentageBreakInfoLine : BreakInfoLine { - public PercentageBreakInfoLine(LocalisableString name, string prefix = "") - : base(name, prefix) + public PercentageBreakInfoLine(LocalisableString name) + : base(name) { } From 6ad8339c6674300806378693d79cc9f12285e71a Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:30:11 +0900 Subject: [PATCH 16/59] use no null when true --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 333dd0fd73..daf1417f6f 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Microsoft.Win32; @@ -180,7 +181,7 @@ namespace osu.Game.Tournament.IPC /// Whether an IPC directory was successfully auto-detected. public bool AutoDetectIPCLocation() => SetIPCLocation(findStablePath()); - private static bool ipcFileExistsInDirectory(string? p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); + private static bool ipcFileExistsInDirectory([NotNullWhen(true)] string? p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); private string? findStablePath() { @@ -201,7 +202,7 @@ namespace osu.Game.Tournament.IPC string? stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); if (ipcFileExistsInDirectory(stableInstallPath)) - return stableInstallPath!; + return stableInstallPath; } catch { From a1f0e5978448040c646e0252ffc7fdf4077beb17 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:30:51 +0900 Subject: [PATCH 17/59] remove null check for b.Beatmap --- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index cfce2694e9..9caa87d75e 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -252,9 +252,6 @@ namespace osu.Game.Tournament.Screens.MapPool foreach (var b in CurrentMatch.Value.Round.Value.Beatmaps) { - if (b.Beatmap == null) - continue; - if (currentFlow == null || (LadderInfo.SplitMapPoolByMods.Value && currentMods != b.Mods)) { mapFlows.Add(currentFlow = new FillFlowContainer From bc2ca11bb0497b81c0a891a34aac645089828e02 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:31:05 +0900 Subject: [PATCH 18/59] move to initialiser --- osu.Game.Tournament/TournamentGameBase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index ee03b4c35d..eecd097a97 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tournament public partial class TournamentGameBase : OsuGameBase { public const string BRACKET_FILENAME = @"bracket.json"; - private LadderInfo ladder = null!; + private LadderInfo ladder = new LadderInfo(); private TournamentStorage storage = null!; private DependencyContainer dependencies = null!; private FileBasedIPC ipc = null!; @@ -77,8 +77,6 @@ namespace osu.Game.Tournament dependencies.CacheAs(new StableInfo(storage)); beatmapCache = dependencies.Get(); - - ladder = new LadderInfo(); } protected override void LoadComplete() From 059012130924902e36d3e8311d23e4381b7d07eb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:38:19 +0900 Subject: [PATCH 19/59] string mod should not null Already assigned in the constructor --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 2d5844d02b..0f916d931d 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Components { public readonly TournamentBeatmap? Beatmap; - private readonly string? mod; + private readonly string mod; public const float HEIGHT = 50; From ba80d1e2d5e766a5791b047fcad736adb4f54340 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:49:13 +0900 Subject: [PATCH 20/59] remove nullable for Box --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 0f916d931d..ba922c7c7b 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tournament.Components private readonly Bindable currentMatch = new Bindable(); - private Box? flash; + private Box flash = null!; public TournamentBeatmapPanel(TournamentBeatmap? beatmap, string mod = "") { @@ -135,11 +135,12 @@ namespace osu.Game.Tournament.Components match.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged; if (match.NewValue != null) match.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged; - updateState(); + + Scheduler.AddOnce(updateState); } private void picksBansOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - => updateState(); + => Scheduler.AddOnce(updateState); private BeatmapChoice? choice; @@ -157,7 +158,7 @@ namespace osu.Game.Tournament.Components if (newChoice != null) { if (shouldFlash) - flash?.FadeOutFromOne(500).Loop(0, 10); + flash.FadeOutFromOne(500).Loop(0, 10); BorderThickness = 6; From 5d09eca1041e10119738707c608340a3d8ddf861 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:49:30 +0900 Subject: [PATCH 21/59] revert test change --- osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index d6941848b7..b76e0d7521 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens { Team1 = { Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA") }, Team2 = { Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN") }, - Round = { Value = Ladder.Rounds.First(g => g.Name.Value == "Quarterfinals") } + Round = { Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals") } }; Add(new TeamIntroScreen From 99dd156d5322ab17a542b855796323fadd981e36 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:50:16 +0900 Subject: [PATCH 22/59] remove useless using --- osu.Game.Tournament/Models/TournamentTeam.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index b3b2f213ce..3cd527aaaa 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; namespace osu.Game.Tournament.Models { From 404a927caf55f05be24d1eadf0f3bda06227d92e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 30 Jul 2023 02:56:52 +0900 Subject: [PATCH 23/59] fix Possible NullReferenceException in test --- .../Components/TestSceneTournamentModDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index cea4306ff8..0cb95c2e43 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tournament.Tests.Components private void success(APIBeatmap beatmap) { - var ruleset = rulesets.GetRuleset(Ladder.Ruleset.Value.OnlineID); + var ruleset = rulesets.GetRuleset(Ladder.Ruleset.Value?.OnlineID ?? -1); if (ruleset == null) return; From 6ebfafa9c3b1f24cc89ec72a577e70a799b052d1 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 29 Jul 2023 11:02:04 -0700 Subject: [PATCH 24/59] Remove unnecessary text comparison --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index cfdf6cc651..3357963fac 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -47,17 +47,7 @@ namespace osu.Game.Screens.Play.Break } }; - Current.ValueChanged += currentValueChanged; - } - - private void currentValueChanged(ValueChangedEvent e) - { - LocalisableString newText = Format(e.NewValue); - - if (valueText.Text == newText) - return; - - valueText.Text = newText; + Current.ValueChanged += text => valueText.Text = Format(text.NewValue); } protected virtual LocalisableString Format(T count) From 4ddf05602f1f117f8ab0248c937a2487e76f59a3 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 29 Jul 2023 11:05:15 -0700 Subject: [PATCH 25/59] Update `BreakInfoLine` to formatting standards --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 34 ++++++++++++-------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 3357963fac..147650ca07 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -21,21 +21,30 @@ namespace osu.Game.Screens.Play.Break public Bindable Current = new Bindable(); - private readonly OsuSpriteText text; - private readonly OsuSpriteText valueText; + private readonly LocalisableString name; + + private OsuSpriteText valueText = null!; public BreakInfoLine(LocalisableString name) { + this.name = name; + AutoSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { Children = new Drawable[] { - text = new OsuSpriteText + new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.CentreRight, Text = name, Font = OsuFont.GetFont(size: 17), - Margin = new MarginPadding { Right = margin } + Margin = new MarginPadding { Right = margin }, + Colour = colours.Yellow, }, valueText = new OsuSpriteText { @@ -43,11 +52,17 @@ namespace osu.Game.Screens.Play.Break Origin = Anchor.CentreLeft, Text = @"-", Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), - Margin = new MarginPadding { Left = margin } + Margin = new MarginPadding { Left = margin }, + Colour = colours.YellowLight, } }; + } - Current.ValueChanged += text => valueText.Text = Format(text.NewValue); + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(text => valueText.Text = Format(text.NewValue), true); } protected virtual LocalisableString Format(T count) @@ -57,13 +72,6 @@ namespace osu.Game.Screens.Play.Break return count.ToString() ?? string.Empty; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - text.Colour = colours.Yellow; - valueText.Colour = colours.YellowLight; - } } public partial class PercentageBreakInfoLine : BreakInfoLine From a618ed140e0bd631f3d0aeba8a625b37c991673d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2023 15:07:06 +0900 Subject: [PATCH 26/59] Move `StoryboardReplacesBackground` bindable more local to usage --- osu.Game/Graphics/Containers/UserDimContainer.cs | 6 ------ osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 9 +++++++-- osu.Game/Screens/Play/Player.cs | 2 -- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 6f6292c3b2..4821e6b370 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -28,11 +28,6 @@ namespace osu.Game.Graphics.Containers /// public readonly Bindable IgnoreUserSettings = new Bindable(); - /// - /// Whether or not the storyboard loaded should completely hide the background behind it. - /// - public readonly Bindable StoryboardReplacesBackground = new Bindable(); - /// /// Whether player is in break time. /// Must be bound to to allow for dim adjustments in gameplay. @@ -83,7 +78,6 @@ namespace osu.Game.Graphics.Containers LightenDuringBreaks.ValueChanged += _ => UpdateVisuals(); IsBreakTime.ValueChanged += _ => UpdateVisuals(); ShowStoryboard.ValueChanged += _ => UpdateVisuals(); - StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); IgnoreUserSettings.ValueChanged += _ => UpdateVisuals(); } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 312fd496a1..8a3755f980 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -36,6 +36,9 @@ namespace osu.Game.Screens.Backgrounds /// public readonly Bindable IgnoreUserSettings = new Bindable(true); + /// + /// Whether or not the storyboard loaded should completely hide the background behind it. + /// public readonly Bindable StoryboardReplacesBackground = new Bindable(); /// @@ -60,12 +63,11 @@ namespace osu.Game.Screens.Backgrounds InternalChild = dimmable = CreateFadeContainer(); + dimmable.StoryboardReplacesBackground.BindTo(StoryboardReplacesBackground); dimmable.IgnoreUserSettings.BindTo(IgnoreUserSettings); dimmable.IsBreakTime.BindTo(IsBreakTime); dimmable.BlurAmount.BindTo(BlurAmount); dimmable.DimWhenUserSettingsIgnored.BindTo(DimWhenUserSettingsIgnored); - - StoryboardReplacesBackground.BindTo(dimmable.StoryboardReplacesBackground); } [BackgroundDependencyLoader] @@ -144,6 +146,8 @@ namespace osu.Game.Screens.Backgrounds /// public readonly Bindable BlurAmount = new BindableFloat(); + public readonly Bindable StoryboardReplacesBackground = new Bindable(); + public Background Background { get => background; @@ -187,6 +191,7 @@ namespace osu.Game.Screens.Backgrounds userBlurLevel.ValueChanged += _ => UpdateVisuals(); BlurAmount.ValueChanged += _ => UpdateVisuals(); + StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); } protected override bool ShowDimContent diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7d67e2657d..5f8e061d89 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1049,8 +1049,6 @@ namespace osu.Game.Screens.Play DimmableStoryboard.IsBreakTime.BindTo(breakTracker.IsBreakTime); - DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); - storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; foreach (var mod in GameplayState.Mods.OfType()) From 0e510088f90e0c177be9f7147be61e39c149c97c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2023 15:50:15 +0900 Subject: [PATCH 27/59] Ensure background of gameplay is black when storyboard is overriding background display --- .../Background/TestSceneUserDimBackgrounds.cs | 26 +++++++++---------- .../Graphics/Containers/UserDimContainer.cs | 7 +++-- .../Backgrounds/BackgroundScreenBeatmap.cs | 13 +++++++--- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index 5df5337a96..566ccd6bd5 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -125,13 +125,13 @@ namespace osu.Game.Tests.Visual.Background createFakeStoryboard(); AddStep("Enable Storyboard", () => { - player.ReplacesBackground.Value = true; + player.StoryboardReplacesBackground.Value = true; player.StoryboardEnabled.Value = true; }); - AddUntilStep("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible); + AddUntilStep("Background is black, storyboard is visible", () => songSelect.IsBackgroundVisible() && songSelect.IsBackgroundBlack() && player.IsStoryboardVisible); AddStep("Disable Storyboard", () => { - player.ReplacesBackground.Value = false; + player.StoryboardReplacesBackground.Value = false; player.StoryboardEnabled.Value = false; }); AddUntilStep("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && !player.IsStoryboardVisible); @@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Background createFakeStoryboard(); AddStep("Enable Storyboard", () => { - player.ReplacesBackground.Value = true; + player.StoryboardReplacesBackground.Value = true; player.StoryboardEnabled.Value = true; }); AddStep("Enable user dim", () => player.DimmableStoryboard.IgnoreUserSettings.Value = false); @@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.Background { performFullSetup(); createFakeStoryboard(); - AddStep("Enable replacing background", () => player.ReplacesBackground.Value = true); + AddStep("Enable replacing background", () => player.StoryboardReplacesBackground.Value = true); AddUntilStep("Storyboard is invisible", () => !player.IsStoryboardVisible); AddUntilStep("Background is visible", () => songSelect.IsBackgroundVisible()); @@ -199,11 +199,11 @@ namespace osu.Game.Tests.Visual.Background player.DimmableStoryboard.IgnoreUserSettings.Value = true; }); AddUntilStep("Storyboard is visible", () => player.IsStoryboardVisible); - AddUntilStep("Background is invisible", () => songSelect.IsBackgroundInvisible()); + AddUntilStep("Background is dimmed", () => songSelect.IsBackgroundVisible() && songSelect.IsBackgroundBlack()); - AddStep("Disable background replacement", () => player.ReplacesBackground.Value = false); + AddStep("Disable background replacement", () => player.StoryboardReplacesBackground.Value = false); AddUntilStep("Storyboard is visible", () => player.IsStoryboardVisible); - AddUntilStep("Background is visible", () => songSelect.IsBackgroundVisible()); + AddUntilStep("Background is visible", () => songSelect.IsBackgroundVisible() && !songSelect.IsBackgroundBlack()); } /// @@ -257,7 +257,7 @@ namespace osu.Game.Tests.Visual.Background private void createFakeStoryboard() => AddStep("Create storyboard", () => { player.StoryboardEnabled.Value = false; - player.ReplacesBackground.Value = false; + player.StoryboardReplacesBackground.Value = false; player.DimmableStoryboard.Add(new OsuSpriteText { Size = new Vector2(500, 50), @@ -323,6 +323,8 @@ namespace osu.Game.Tests.Visual.Background config.BindWith(OsuSetting.BlurLevel, BlurLevel); } + public bool IsBackgroundBlack() => background.CurrentColour == OsuColour.Gray(0); + public bool IsBackgroundDimmed() => background.CurrentColour == OsuColour.Gray(1f - background.CurrentDim); public bool IsBackgroundUndimmed() => background.CurrentColour == Color4.White; @@ -331,8 +333,6 @@ namespace osu.Game.Tests.Visual.Background public bool IsUserBlurDisabled() => background.CurrentBlur == new Vector2(0); - public bool IsBackgroundInvisible() => background.CurrentAlpha == 0; - public bool IsBackgroundVisible() => background.CurrentAlpha == 1; public bool IsBackgroundBlur() => Precision.AlmostEquals(background.CurrentBlur, new Vector2(BACKGROUND_BLUR), 0.1f); @@ -367,7 +367,7 @@ namespace osu.Game.Tests.Visual.Background { base.OnEntering(e); - ApplyToBackground(b => ReplacesBackground.BindTo(b.StoryboardReplacesBackground)); + ApplyToBackground(b => StoryboardReplacesBackground.BindTo(b.StoryboardReplacesBackground)); } public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard; @@ -376,7 +376,7 @@ namespace osu.Game.Tests.Visual.Background public bool BlockLoad; public Bindable StoryboardEnabled; - public readonly Bindable ReplacesBackground = new Bindable(); + public readonly Bindable StoryboardReplacesBackground = new Bindable(); public readonly Bindable IsPaused = new Bindable(); public LoadBlockingTestPlayer(bool allowPause = true) diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 4821e6b370..625702ef6e 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -24,8 +24,11 @@ namespace osu.Game.Graphics.Containers public const double BACKGROUND_FADE_DURATION = 800; /// - /// Whether or not user-configured settings relating to brightness of elements should be ignored + /// Whether or not user-configured settings relating to brightness of elements should be ignored. /// + /// + /// For best or worst, this also bypasses storyboard disable. Not sure this is correct but leaving it as to not break anything. + /// public readonly Bindable IgnoreUserSettings = new Bindable(); /// @@ -52,7 +55,7 @@ namespace osu.Game.Graphics.Containers private float breakLightening => LightenDuringBreaks.Value && IsBreakTime.Value ? BREAK_LIGHTEN_AMOUNT : 0; - protected float DimLevel => Math.Max(!IgnoreUserSettings.Value ? (float)UserDimLevel.Value - breakLightening : DimWhenUserSettingsIgnored.Value, 0); + protected virtual float DimLevel => Math.Max(!IgnoreUserSettings.Value ? (float)UserDimLevel.Value - breakLightening : DimWhenUserSettingsIgnored.Value, 0); protected override Container Content => dimContent; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 8a3755f980..1506b884b4 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -194,9 +194,16 @@ namespace osu.Game.Screens.Backgrounds StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); } - protected override bool ShowDimContent - // The background needs to be hidden in the case of it being replaced by the storyboard - => (!ShowStoryboard.Value && !IgnoreUserSettings.Value) || !StoryboardReplacesBackground.Value; + protected override float DimLevel + { + get + { + if ((IgnoreUserSettings.Value || ShowStoryboard.Value) && StoryboardReplacesBackground.Value) + return 1; + + return base.DimLevel; + } + } protected override void UpdateVisuals() { From 14d87e49c75e423ac34c0e5276f32dda93880bdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2023 16:49:58 +0900 Subject: [PATCH 28/59] Improve choice of where to start playback of multiplayer spectator --- .../Spectate/MultiSpectatorScreen.cs | 32 ++++++++++++++----- .../Spectate/SpectatorSyncManager.cs | 2 +- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index afc10d0c0a..bb1a139cf7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -2,12 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; @@ -198,15 +199,29 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private void performInitialSeek() { - // Seek the master clock to the gameplay time. - // This is chosen as the first available frame in the players' replays, which matches the seek by each individual SpectatorPlayer. - double startTime = instances.Where(i => i.Score != null) - .SelectMany(i => i.Score.AsNonNull().Replay.Frames) - .Select(f => f.Time) - .DefaultIfEmpty(0) - .Min(); + // We want to start showing gameplay as soon as possible. + // Each client may be in a different place in the beatmap, so we need to do our best to find a common + // starting point. + // + // Preferring a lower value ensures that we don't have some clients stuttering to keep up. + List minFrameTimes = new List(); + + foreach (var instance in instances) + { + if (instance.Score == null) + continue; + + minFrameTimes.Add(instance.Score.Replay.Frames.Min(f => f.Time)); + } + + // Remove any outliers (only need to worry about removing those lower than the mean since we will take a Min() after. + double mean = minFrameTimes.Average(); + minFrameTimes.RemoveAll(t => mean - t > 1000); + + double startTime = minFrameTimes.Min(); masterClockContainer.Reset(startTime, true); + Logger.Log($"Multiplayer spectator seeking to initial time of {startTime}"); } protected override void OnNewPlayingUserState(int userId, SpectatorState spectatorState) @@ -245,6 +260,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate return base.OnBackButton(); // On a manual exit, set the player back to idle unless gameplay has finished. + // Of note, this doesn't cover exiting using alt-f4 or menu home option. if (multiplayerClient.Room.State != MultiplayerRoomState.Open) multiplayerClient.ChangeState(MultiplayerUserState.Idle); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs index 615c0d7c2b..fd61b60fe4 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/SpectatorSyncManager.cs @@ -182,7 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate return; masterState = newState; - Logger.Log($"{nameof(SpectatorSyncManager)}'s master clock become {masterState}"); + Logger.Log($"{nameof(SpectatorSyncManager)}'s master clock became {masterState}"); switch (masterState) { From 75c1d5ad7feaf9fd81d9ddd83e5650961e98a952 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 2 Aug 2023 18:02:11 +0900 Subject: [PATCH 29/59] Add lenience to `FramedBeatmapClock` workaround --- osu.Game/Beatmaps/FramedBeatmapClock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/FramedBeatmapClock.cs b/osu.Game/Beatmaps/FramedBeatmapClock.cs index 399e2fde7f..9577d1e38b 100644 --- a/osu.Game/Beatmaps/FramedBeatmapClock.cs +++ b/osu.Game/Beatmaps/FramedBeatmapClock.cs @@ -124,7 +124,7 @@ namespace osu.Game.Beatmaps { base.Update(); - if (Source != null && Source is not IAdjustableClock && Source.CurrentTime < decoupledClock.CurrentTime) + if (Source != null && Source is not IAdjustableClock && Source.CurrentTime < decoupledClock.CurrentTime - 100) { // InterpolatingFramedClock won't interpolate backwards unless its source has an ElapsedFrameTime. // See https://github.com/ppy/osu-framework/blob/ba1385330cc501f34937e08257e586c84e35d772/osu.Framework/Timing/InterpolatingFramedClock.cs#L91-L93 From aab462fd95534417aa5b3b65918d021a9907885c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 2 Aug 2023 09:40:22 -0700 Subject: [PATCH 30/59] Fix `valueText` being replaced even if current is not binding to anything --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 7 +------ osu.Game/Screens/Play/BreakOverlay.cs | 17 +++++++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 147650ca07..df71767f82 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -56,13 +56,8 @@ namespace osu.Game.Screens.Play.Break Colour = colours.YellowLight, } }; - } - protected override void LoadComplete() - { - base.LoadComplete(); - - Current.BindValueChanged(text => valueText.Text = Format(text.NewValue), true); + Current.BindValueChanged(text => valueText.Text = Format(text.NewValue)); } protected virtual LocalisableString Format(T count) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 4927800059..3ca82ec00b 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -46,13 +46,14 @@ namespace osu.Game.Screens.Play private readonly Container remainingTimeBox; private readonly RemainingTimeCounter remainingTimeCounter; private readonly BreakArrows breakArrows; + private readonly ScoreProcessor scoreProcessor; + private readonly BreakInfo info; public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor) { + this.scoreProcessor = scoreProcessor; RelativeSizeAxes = Axes.Both; - BreakInfo info; - Child = fadeContainer = new Container { Alpha = 0, @@ -102,18 +103,18 @@ namespace osu.Game.Screens.Play } } }; - - if (scoreProcessor != null) - { - info.AccuracyDisplay.Current.BindTo(scoreProcessor.Accuracy); - info.GradeDisplay.Current.BindTo(scoreProcessor.Rank); - } } protected override void LoadComplete() { base.LoadComplete(); initializeBreaks(); + + if (scoreProcessor != null) + { + info.AccuracyDisplay.Current.BindTo(scoreProcessor.Accuracy); + info.GradeDisplay.Current.BindTo(scoreProcessor.Rank); + } } private void initializeBreaks() From f38b21110f0e60a1667f3f2cb7c21fa5936b6122 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Aug 2023 08:57:43 +0900 Subject: [PATCH 31/59] Add missing parenthesis to comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index bb1a139cf7..66524f66ae 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -214,7 +214,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate minFrameTimes.Add(instance.Score.Replay.Frames.Min(f => f.Time)); } - // Remove any outliers (only need to worry about removing those lower than the mean since we will take a Min() after. + // Remove any outliers (only need to worry about removing those lower than the mean since we will take a Min() after). double mean = minFrameTimes.Average(); minFrameTimes.RemoveAll(t => mean - t > 1000); From 71f6e5731d9e7b0990f1a56aa03343466be6d193 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Aug 2023 08:58:19 +0900 Subject: [PATCH 32/59] Fix potential null reference if no frames found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 66524f66ae..c1b1127542 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -211,7 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate if (instance.Score == null) continue; - minFrameTimes.Add(instance.Score.Replay.Frames.Min(f => f.Time)); + minFrameTimes.Add(instance.Score.Replay.Frames.MinBy(f => f.Time)?.Time ?? 0); } // Remove any outliers (only need to worry about removing those lower than the mean since we will take a Min() after). From d39ef48b71bb346932a10f69bdb315782666be15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Aug 2023 09:01:11 +0900 Subject: [PATCH 33/59] Return `null` intead of `FileNotFoundException` on missing file in `ZipArchiveReader` --- osu.Game/IO/Archives/ZipArchiveReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 1fca8aa055..5ef03b3641 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -31,7 +31,7 @@ namespace osu.Game.IO.Archives { ZipArchiveEntry entry = archive.Entries.SingleOrDefault(e => e.Key == name); if (entry == null) - throw new FileNotFoundException(); + return null; var owner = MemoryAllocator.Default.Allocate((int)entry.Size); From 52b1073d937fbd91112bc5b1dee0f660f8bc09ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 3 Aug 2023 21:08:00 +0200 Subject: [PATCH 34/59] Fix playfield skin layer not rotating correctly with barrel roll mod --- osu.Game/Screens/Play/HUDOverlay.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 536d3ac146..43c61588b1 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -242,7 +242,9 @@ namespace osu.Game.Screens.Play Quad playfieldScreenSpaceDrawQuad = drawableRuleset.Playfield.SkinnableComponentScreenSpaceDrawQuad; playfieldComponents.Position = ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); - playfieldComponents.Size = ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft); + playfieldComponents.Width = (ToLocalSpace(playfieldScreenSpaceDrawQuad.TopRight) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft)).Length; + playfieldComponents.Height = (ToLocalSpace(playfieldScreenSpaceDrawQuad.BottomLeft) - ToLocalSpace(playfieldScreenSpaceDrawQuad.TopLeft)).Length; + playfieldComponents.Rotation = drawableRuleset.Playfield.Rotation; } float? lowestTopScreenSpaceLeft = null; From d179fe3d96919ed33105d0f489c3bbbda23dd721 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 3 Aug 2023 23:09:39 -0700 Subject: [PATCH 35/59] Add support for changelog entries with url attached --- .../Online/TestSceneChangelogOverlay.cs | 9 +++++++- osu.Game/Overlays/Changelog/ChangelogEntry.cs | 22 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 8d61c5df9f..040b903636 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -154,7 +154,14 @@ namespace osu.Game.Tests.Visual.Online Type = ChangelogEntryType.Misc, Category = "Code quality", Title = "Clean up another thing" - } + }, + new APIChangelogEntry + { + Type = ChangelogEntryType.Add, + Category = "osu!", + Title = "Add entry with news url", + Url = "https://osu.ppy.sh/home/news/2023-07-27-summer-splash" + }, } }); diff --git a/osu.Game/Overlays/Changelog/ChangelogEntry.cs b/osu.Game/Overlays/Changelog/ChangelogEntry.cs index 06ec2043f9..9c40440778 100644 --- a/osu.Game/Overlays/Changelog/ChangelogEntry.cs +++ b/osu.Game/Overlays/Changelog/ChangelogEntry.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osuTK; using osuTK.Graphics; @@ -29,6 +30,9 @@ namespace osu.Game.Overlays.Changelog [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; + [Resolved] + private ILinkHandler? linkHandler { get; set; } + private FontUsage fontLarge; private FontUsage fontMedium; @@ -86,11 +90,21 @@ namespace osu.Game.Overlays.Changelog } }; - title.AddText(entry.Title, t => + if (string.IsNullOrEmpty(entry.Url)) { - t.Font = fontLarge; - t.Colour = entryColour; - }); + title.AddText(entry.Title, t => + { + t.Font = fontLarge; + t.Colour = entryColour; + }); + } + else + { + title.AddLink(entry.Title, () => linkHandler?.HandleLink(entry.Url), entry.Url, t => + { + t.Font = fontLarge; + }); + } if (!string.IsNullOrEmpty(entry.Repository) && !string.IsNullOrEmpty(entry.GithubUrl)) addRepositoryReference(title, entryColour); From 49f5d6813ec82dec79ef02e8b380fde4cc7a44d8 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 4 Aug 2023 22:05:59 -0700 Subject: [PATCH 36/59] Block beatmap editor from testing/exiting/exporting when saving fails --- osu.Game/Screens/Edit/Editor.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b885eee46f..35d8bb4ab7 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -425,7 +425,8 @@ namespace osu.Game.Screens.Edit { dialogOverlay.Push(new SaveBeforeGameplayTestDialog(() => { - Save(); + if (!Save()) return; + pushEditorPlayer(); })); } @@ -764,7 +765,7 @@ namespace osu.Game.Screens.Edit private void confirmExitWithSave() { - Save(); + if (!Save()) return; ExitConfirmed = true; this.Exit(); @@ -1021,13 +1022,15 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() { - Save(); + if (!Save()) return; + beatmapManager.Export(Beatmap.Value.BeatmapSetInfo); } private void exportLegacyBeatmap() { - Save(); + if (!Save()) return; + beatmapManager.ExportLegacy(Beatmap.Value.BeatmapSetInfo); } From d91798271d80fe735e2f0c9ff72c6faf30fe0525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 8 Aug 2023 22:06:30 +0200 Subject: [PATCH 37/59] Add test case covering exit block Co-authored-by: Joseph Madamba --- .../Editing/TestSceneEditorBeatmapCreation.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 5aa2dd2ebf..37cb43a43a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -18,6 +18,7 @@ using osu.Game.Database; using osu.Game.Overlays.Dialog; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; +using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; @@ -453,6 +454,51 @@ namespace osu.Game.Tests.Visual.Editing }); } + [Test] + public void TestExitBlockedWhenSavingBeatmapWithSameNamedDifficulties() + { + Guid setId = Guid.Empty; + const string duplicate_difficulty_name = "duplicate"; + + AddStep("retrieve set ID", () => setId = EditorBeatmap.BeatmapInfo.BeatmapSet!.ID); + AddStep("set difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = duplicate_difficulty_name); + AddStep("save beatmap", () => Editor.Save()); + AddAssert("new beatmap persisted", () => + { + var set = beatmapManager.QueryBeatmapSet(s => s.ID == setId); + return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1); + }); + + AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new CatchRuleset().RulesetInfo)); + + AddUntilStep("wait for created", () => + { + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + return difficultyName != null && difficultyName != duplicate_difficulty_name; + }); + AddUntilStep("wait for editor load", () => Editor.IsLoaded && DialogOverlay.IsLoaded); + + AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[] + { + new Fruit + { + StartTime = 0 + }, + new Fruit + { + StartTime = 1000 + } + })); + + AddStep("set difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = duplicate_difficulty_name); + AddUntilStep("wait for has unsaved changes", () => Editor.HasUnsavedChanges); + + AddStep("exit", () => Editor.Exit()); + AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is PromptForSaveDialog); + AddStep("attempt to save", () => DialogOverlay.CurrentDialog.PerformOkAction()); + AddAssert("editor is still current", () => Editor.IsCurrentScreen()); + } + [Test] public void TestCreateNewDifficultyForInconvertibleRuleset() { From c88045dfc7251dde653bd666f3ebf1b7be4fb809 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Aug 2023 18:21:57 +0900 Subject: [PATCH 38/59] Fix weird usage of `Cast` --- osu.Game.Tournament/Models/TournamentTeam.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index 3cd527aaaa..5df8c2a620 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tournament.Models { int[] ranks = Players.Select(p => p.Rank) .Where(i => i.HasValue) - .Cast() + .Select(i => i!.Value) .ToArray(); if (ranks.Length == 0) From 5898a9986b2ee8dc12628f7e2ff880a367457d46 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 9 Aug 2023 19:11:36 +0900 Subject: [PATCH 39/59] Revert "use no null when true" This reverts commit 6ad8339c6674300806378693d79cc9f12285e71a. --- osu.Game.Tournament/IPC/FileBasedIPC.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index daf1417f6f..333dd0fd73 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Microsoft.Win32; @@ -181,7 +180,7 @@ namespace osu.Game.Tournament.IPC /// Whether an IPC directory was successfully auto-detected. public bool AutoDetectIPCLocation() => SetIPCLocation(findStablePath()); - private static bool ipcFileExistsInDirectory([NotNullWhen(true)] string? p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); + private static bool ipcFileExistsInDirectory(string? p) => p != null && File.Exists(Path.Combine(p, "ipc.txt")); private string? findStablePath() { @@ -202,7 +201,7 @@ namespace osu.Game.Tournament.IPC string? stableInstallPath = Environment.GetEnvironmentVariable("OSU_STABLE_PATH"); if (ipcFileExistsInDirectory(stableInstallPath)) - return stableInstallPath; + return stableInstallPath!; } catch { From 5ad80879b771015b757823b9fd322ebe7b1c87f1 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 9 Aug 2023 19:11:51 +0900 Subject: [PATCH 40/59] let MatchIPCInfo .Beatmap be nullable --- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 3 ++- osu.Game.Tournament/IPC/MatchIPCInfo.cs | 2 +- osu.Game.Tournament/Screens/BeatmapInfoScreen.cs | 2 +- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 19d63286d8..fa0cbda16b 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tournament.Components [Resolved] private IBindable ruleset { get; set; } = null!; - public TournamentBeatmap Beatmap + public TournamentBeatmap? Beatmap { set { diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 333dd0fd73..bf835122cc 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -87,12 +87,13 @@ namespace osu.Game.Tournament.IPC var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId); - if (existing?.Beatmap != null) + if (existing != null) Beatmap.Value = existing.Beatmap; else { beatmapLookupRequest = new GetBeatmapRequest(new APIBeatmap { OnlineID = beatmapId }); beatmapLookupRequest.Success += b => Beatmap.Value = new TournamentBeatmap(b); + beatmapLookupRequest.Failure += _ => Beatmap.Value = null; API.Queue(beatmapLookupRequest); } } diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index ff557717d5..f57518971f 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tournament.IPC { public partial class MatchIPCInfo : Component { - public Bindable Beatmap { get; } = new Bindable(); + public Bindable Beatmap { get; } = new Bindable(); public Bindable Mods { get; } = new Bindable(); public Bindable State { get; } = new Bindable(); public Bindable ChatChannel { get; } = new Bindable(); diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index e977012803..32a50d2222 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tournament.Screens SongBar.Mods = mods.NewValue; } - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { SongBar.FadeInFromZero(300, Easing.OutQuint); SongBar.Beatmap = beatmap.NewValue; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 9caa87d75e..07dc2bea54 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -121,13 +121,13 @@ namespace osu.Game.Tournament.Screens.MapPool splitMapPoolByMods.BindValueChanged(_ => updateDisplay()); } - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { if (CurrentMatch.Value == null || CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) return; // if bans have already been placed, beatmap changes result in a selection being made autoamtically - if (beatmap.NewValue.OnlineID > 0) + if (beatmap.NewValue?.OnlineID > 0) addForBeatmap(beatmap.NewValue.OnlineID); } From 6549ca530480828076c7bd372cb8fec764189260 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Aug 2023 00:20:37 +0900 Subject: [PATCH 41/59] Revert some usages of `AsNonNull()` in tests We generally prefer `!` when it is unambiguous usage (ie. direct access). --- .../NonVisual/LadderInfoSerialisationTest.cs | 5 ++--- .../Screens/TestSceneMapPoolScreen.cs | 15 +++++++-------- osu.Game.Tournament.Tests/TournamentTestScene.cs | 7 +++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs index d18651b8bb..acb4a87ffc 100644 --- a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -3,7 +3,6 @@ using Newtonsoft.Json; using NUnit.Framework; -using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.NonVisual @@ -36,8 +35,8 @@ namespace osu.Game.Tournament.Tests.NonVisual PlayersPerTeam = { Value = 4 }, Teams = { - match.Team1.Value.AsNonNull(), - match.Team2.Value.AsNonNull(), + match.Team1.Value!, + match.Team2.Value!, }, Rounds = { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 254d5c6996..7b2c1ba336 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -4,7 +4,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Tournament.Components; @@ -31,7 +30,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load few maps", () => { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Clear(); for (int i = 0; i < 8; i++) addBeatmap(); @@ -51,7 +50,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load just enough maps", () => { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Clear(); for (int i = 0; i < 18; i++) addBeatmap(); @@ -71,7 +70,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Clear(); for (int i = 0; i < 19; i++) addBeatmap(); @@ -91,7 +90,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Clear(); for (int i = 0; i < 11; i++) addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); @@ -117,7 +116,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Clear(); for (int i = 0; i < 12; i++) addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); @@ -137,7 +136,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("load many maps", () => { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Clear(); + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Clear(); for (int i = 0; i < 12; i++) addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); @@ -154,7 +153,7 @@ namespace osu.Game.Tournament.Tests.Screens private void addBeatmap(string mods = "NM") { - Ladder.CurrentMatch.Value.AsNonNull().Round.Value.AsNonNull().Beatmaps.Add(new RoundBeatmap + Ladder.CurrentMatch.Value!.Round.Value!.Beatmaps.Add(new RoundBeatmap { Beatmap = CreateSampleBeatmap(), Mods = mods diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 0cf1e22211..f24fc61d85 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading; using osu.Framework.Allocation; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; @@ -41,10 +40,10 @@ namespace osu.Game.Tournament.Tests match = CreateSampleMatch(); - Ladder.Rounds.Add(match.Round.Value.AsNonNull()); + Ladder.Rounds.Add(match.Round.Value!); Ladder.Matches.Add(match); - Ladder.Teams.Add(match.Team1.Value.AsNonNull()); - Ladder.Teams.Add(match.Team2.Value.AsNonNull()); + Ladder.Teams.Add(match.Team1.Value!); + Ladder.Teams.Add(match.Team2.Value!); Ruleset.BindTo(Ladder.Ruleset); Dependencies.CacheAs(new StableInfo(storage)); From 4e83245acfc61c0460fc4882935d5b7e64b04e09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Aug 2023 00:24:57 +0900 Subject: [PATCH 42/59] Apply nullability to all remaining tests where it wasn't applied --- .../Components/TestSceneDateTextBox.cs | 2 -- osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs | 4 +--- .../Components/TestSceneTournamentModDisplay.cs | 2 -- osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs | 2 -- osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs | 6 ++---- osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs | 4 +--- .../Screens/TestSceneGameplayScreen.cs | 2 -- .../Screens/TestSceneScheduleScreen.cs | 2 -- 8 files changed, 4 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs index f547acd635..c1651b8ce3 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs b/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs index f793c33878..762cfa2519 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -22,7 +20,7 @@ namespace osu.Game.Tournament.Tests.Components [Test] public void TestSongBar() { - SongBar songBar = null; + SongBar songBar = null!; AddStep("create bar", () => Child = songBar = new SongBar { diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 0cb95c2e43..99a448c494 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs index 256a984a7c..014c96b075 100644 --- a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.IO; using System.Threading.Tasks; diff --git a/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs b/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs index ca6354cb48..6ee7808099 100644 --- a/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.IO; using System.Linq; using NUnit.Framework; @@ -36,11 +34,11 @@ namespace osu.Game.Tournament.Tests.NonVisual { var osu = LoadTournament(host); TournamentStorage storage = (TournamentStorage)osu.Dependencies.Get(); - FileBasedIPC ipc = null; + FileBasedIPC? ipc = null; WaitForOrAssert(() => (ipc = osu.Dependencies.Get() as FileBasedIPC)?.IsLoaded == true, @"ipc could not be populated in a reasonable amount of time"); - Assert.True(ipc.SetIPCLocation(testStableInstallDirectory)); + Assert.True(ipc!.SetIPCLocation(testStableInstallDirectory)); Assert.True(storage.AllTournaments.Exists("stable.json")); } finally diff --git a/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs b/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs index 8dc0946432..e4a35913cc 100644 --- a/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Threading; using System.Threading.Tasks; @@ -13,7 +11,7 @@ namespace osu.Game.Tournament.Tests.NonVisual { public abstract class TournamentHostTest { - public static TournamentGameBase LoadTournament(GameHost host, TournamentGameBase tournament = null) + public static TournamentGameBase LoadTournament(GameHost host, TournamentGameBase? tournament = null) { tournament ??= new TournamentGameBase(); Task.Factory.StartNew(() => host.Run(tournament), TaskCreationOptions.LongRunning) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index abf0905647..31583bf8b7 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs index 5071fbbfe3..f3c3fdec97 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using NUnit.Framework; using osu.Framework.Allocation; From 3501b7c22b9820292cc9b28ca0caadef6255c82e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 9 Aug 2023 21:32:46 +0200 Subject: [PATCH 43/59] Fix some more nullability inspections --- .../Components/TestSceneDateTextBox.cs | 2 +- .../Components/TestSceneTournamentModDisplay.cs | 6 +++--- osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs index c1651b8ce3..d018a7ed5c 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tournament.Tests.Components { public partial class TestSceneDateTextBox : OsuManualInputManagerTestScene { - private DateTextBox textBox; + private DateTextBox textBox = null!; [SetUp] public void Setup() => Schedule(() => diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 99a448c494..0b69da78a4 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -17,12 +17,12 @@ namespace osu.Game.Tournament.Tests.Components public partial class TestSceneTournamentModDisplay : TournamentTestScene { [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; [Resolved] - private IRulesetStore rulesets { get; set; } + private IRulesetStore rulesets { get; set; } = null!; - private FillFlowContainer fillFlow; + private FillFlowContainer fillFlow = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs index 014c96b075..e8c9f65608 100644 --- a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs @@ -79,11 +79,11 @@ namespace osu.Game.Tournament.Tests.NonVisual public partial class TestTournament : TournamentGameBase { private readonly bool resetRuleset; - private readonly Action runOnLoadComplete; + private readonly Action? runOnLoadComplete; public new Task BracketLoadTask => base.BracketLoadTask; - public TestTournament(bool resetRuleset = false, [InstantHandle] Action runOnLoadComplete = null) + public TestTournament(bool resetRuleset = false, [InstantHandle] Action? runOnLoadComplete = null) { this.resetRuleset = resetRuleset; this.runOnLoadComplete = runOnLoadComplete; From 896cbb0ba074474858e222253a34b449a7869bea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Aug 2023 21:34:59 +0900 Subject: [PATCH 44/59] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 651e5b1fe6..1ac85532b8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - +