From 9eecb23fefa623356228bc916dba930e784dc035 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 10 Jun 2021 21:35:52 +0900 Subject: [PATCH 001/119] Only seek to the end on first frame arrival --- osu.Game/Screens/Play/SpectatorPlayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 0286b6b8a6..304bc4d7ed 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -48,7 +48,6 @@ namespace osu.Game.Screens.Play base.StartGameplay(); spectatorClient.OnNewFrames += userSentFrames; - seekToGameplay(); } private void userSentFrames(int userId, FrameDataBundle bundle) From 5073ede115f1c3da87e4c8055b8b39bbde31bdd8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 10 Jun 2021 21:38:20 +0900 Subject: [PATCH 002/119] Clear existing frames when starting gameplay --- osu.Game/Screens/Play/SpectatorPlayer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 304bc4d7ed..4d3b5eefb1 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -47,6 +47,8 @@ namespace osu.Game.Screens.Play { base.StartGameplay(); + // Start gameplay along with the very first arrival frame (the latest one). + score.Replay.Frames.Clear(); spectatorClient.OnNewFrames += userSentFrames; } From e18f4cd4bae79bd52801857a6e4deeefff3f35d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 10 Jun 2021 21:39:13 +0900 Subject: [PATCH 003/119] Combine methods --- osu.Game/Screens/Play/SpectatorPlayer.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 4d3b5eefb1..f662a479ec 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -63,6 +63,8 @@ namespace osu.Game.Screens.Play if (!this.IsCurrentScreen()) return; + bool isFirstBundle = score.Replay.Frames.Count == 0; + foreach (var frame in bundle.Frames) { IConvertibleReplayFrame convertibleFrame = GameplayRuleset.CreateConvertibleReplayFrame(); @@ -74,19 +76,8 @@ namespace osu.Game.Screens.Play score.Replay.Frames.Add(convertedFrame); } - seekToGameplay(); - } - - private bool seekedToGameplay; - - private void seekToGameplay() - { - if (seekedToGameplay || score.Replay.Frames.Count == 0) - return; - - NonFrameStableSeek(score.Replay.Frames[0].Time); - - seekedToGameplay = true; + if (isFirstBundle && score.Replay.Frames.Count > 0) + NonFrameStableSeek(score.Replay.Frames[0].Time); } protected override Score CreateScore() => score; From 58d71e4aead45fd8a756d574d904ded7ee5e3e3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 10 Jun 2021 22:41:38 +0900 Subject: [PATCH 004/119] Remove local "next frame" storage --- .../Visual/Gameplay/TestSceneSpectator.cs | 17 +++---- .../TestSceneMultiSpectatorLeaderboard.cs | 4 +- .../TestSceneMultiSpectatorScreen.cs | 12 +---- .../Visual/Spectator/TestSpectatorClient.cs | 44 ++++++++++++++----- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 6eeb3596a8..0926b8778b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -41,8 +41,6 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private OsuGameBase game { get; set; } - private int nextFrame; - private BeatmapSetInfo importedBeatmap; private int importedBeatmapId; @@ -51,8 +49,6 @@ namespace osu.Game.Tests.Visual.Gameplay { base.SetUpSteps(); - AddStep("reset sent frames", () => nextFrame = 0); - AddStep("import beatmap", () => { importedBeatmap = ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Result; @@ -105,7 +101,8 @@ namespace osu.Game.Tests.Visual.Gameplay waitForPlayer(); checkPaused(true); - sendFrames(1000); // send enough frames to ensure play won't be paused + // send enough frames to ensure play won't be paused + sendFrames(100); checkPaused(false); } @@ -114,12 +111,12 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestSpectatingDuringGameplay() { start(); + sendFrames(300); loadSpectatingScreen(); waitForPlayer(); - AddStep("advance frame count", () => nextFrame = 300); - sendFrames(); + sendFrames(300); AddUntilStep("playing from correct point in time", () => player.ChildrenOfType().First().FrameStableClock.CurrentTime > 30000); } @@ -220,11 +217,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void sendFrames(int count = 10) { - AddStep("send frames", () => - { - testSpectatorClient.SendFrames(streamingUser.Id, nextFrame, count); - nextFrame += count; - }); + AddStep("send frames", () => testSpectatorClient.SendFrames(streamingUser.Id, count)); } private void loadSpectatingScreen() diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 5ad35be0ec..7f8a44fb98 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -96,10 +96,10 @@ namespace osu.Game.Tests.Visual.Multiplayer // For player 2, send frames in sets of 10. for (int i = 0; i < 100; i++) { - spectatorClient.SendFrames(PLAYER_1_ID, i, 1); + spectatorClient.SendFrames(PLAYER_1_ID, 1); if (i % 10 == 0) - spectatorClient.SendFrames(PLAYER_2_ID, i, 10); + spectatorClient.SendFrames(PLAYER_2_ID, 10); } }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index b91391c409..f5032fc2a5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -37,7 +37,6 @@ namespace osu.Game.Tests.Visual.Multiplayer private MultiSpectatorScreen spectatorScreen; private readonly List playingUserIds = new List(); - private readonly Dictionary nextFrame = new Dictionary(); private BeatmapSetInfo importedSet; private BeatmapInfo importedBeatmap; @@ -55,8 +54,6 @@ namespace osu.Game.Tests.Visual.Multiplayer { base.SetUpSteps(); - AddStep("reset sent frames", () => nextFrame.Clear()); - AddStep("add streaming client", () => { Remove(spectatorClient); @@ -80,8 +77,6 @@ namespace osu.Game.Tests.Visual.Multiplayer Client.CurrentMatchPlayingUserIds.Add(PLAYER_2_ID); playingUserIds.Add(PLAYER_1_ID); playingUserIds.Add(PLAYER_2_ID); - nextFrame[PLAYER_1_ID] = 0; - nextFrame[PLAYER_2_ID] = 0; }); loadSpectateScreen(false); @@ -253,7 +248,6 @@ namespace osu.Game.Tests.Visual.Multiplayer Client.CurrentMatchPlayingUserIds.Add(id); spectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUserIds.Add(id); - nextFrame[id] = 0; } }); } @@ -264,7 +258,6 @@ namespace osu.Game.Tests.Visual.Multiplayer { spectatorClient.EndPlay(userId); playingUserIds.Remove(userId); - nextFrame.Remove(userId); }); } @@ -275,10 +268,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("send frames", () => { foreach (int id in userIds) - { - spectatorClient.SendFrames(id, nextFrame[id], count); - nextFrame[id] += count; - } + spectatorClient.SendFrames(id, count); }); } diff --git a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs index c7aa43b377..f206d4f8b0 100644 --- a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs +++ b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs @@ -20,9 +20,15 @@ namespace osu.Game.Tests.Visual.Spectator { public class TestSpectatorClient : SpectatorClient { + /// + /// Maximum number of frames sent per bundle via . + /// + public const int FRAME_BUNDLE_SIZE = 10; + public override IBindable IsConnected { get; } = new Bindable(true); private readonly Dictionary userBeatmapDictionary = new Dictionary(); + private readonly Dictionary userNextFrameDictionary = new Dictionary(); [Resolved] private IAPIProvider api { get; set; } = null!; @@ -35,6 +41,7 @@ namespace osu.Game.Tests.Visual.Spectator public void StartPlay(int userId, int beatmapId) { userBeatmapDictionary[userId] = beatmapId; + userNextFrameDictionary[userId] = 0; sendPlayingState(userId); } @@ -57,24 +64,41 @@ namespace osu.Game.Tests.Visual.Spectator public new void Schedule(Action action) => base.Schedule(action); /// - /// Sends frames for an arbitrary user. + /// Sends frames for an arbitrary user, in bundles containing 10 frames each. /// /// The user to send frames for. - /// The frame index. - /// The number of frames to send. - public void SendFrames(int userId, int index, int count) + /// The total number of frames to send. + public void SendFrames(int userId, int count) { var frames = new List(); - for (int i = index; i < index + count; i++) - { - var buttonState = i == index + count - 1 ? ReplayButtonState.None : ReplayButtonState.Left1; + int currentFrameIndex = userNextFrameDictionary[userId]; + int lastFrameIndex = currentFrameIndex + count - 1; - frames.Add(new LegacyReplayFrame(i * 100, RNG.Next(0, 512), RNG.Next(0, 512), buttonState)); + for (; currentFrameIndex <= lastFrameIndex; currentFrameIndex++) + { + // This is done in the next frame so that currentFrameIndex is updated to the correct value. + if (frames.Count == FRAME_BUNDLE_SIZE) + flush(); + + var buttonState = currentFrameIndex == lastFrameIndex ? ReplayButtonState.None : ReplayButtonState.Left1; + frames.Add(new LegacyReplayFrame(currentFrameIndex * 100, RNG.Next(0, 512), RNG.Next(0, 512), buttonState)); } - var bundle = new FrameDataBundle(new ScoreInfo { Combo = index + count }, frames); - ((ISpectatorClient)this).UserSentFrames(userId, bundle); + flush(); + + userNextFrameDictionary[userId] = currentFrameIndex; + + void flush() + { + if (frames.Count == 0) + return; + + var bundle = new FrameDataBundle(new ScoreInfo { Combo = currentFrameIndex }, frames.ToArray()); + ((ISpectatorClient)this).UserSentFrames(userId, bundle); + + frames.Clear(); + } } protected override Task BeginPlayingInternal(SpectatorState state) From 169c98f963e3703e6d2166081b43ab3ac3dec66a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 11 Jun 2021 00:25:19 +0300 Subject: [PATCH 005/119] Add skin providing ruleset resources in `RulesetSkinProvidingContainer` --- osu.Game/Skinning/RulesetResourcesSkin.cs | 51 +++++++++++++++++++ .../Skinning/RulesetSkinProvidingContainer.cs | 10 ++++ 2 files changed, 61 insertions(+) create mode 100644 osu.Game/Skinning/RulesetResourcesSkin.cs diff --git a/osu.Game/Skinning/RulesetResourcesSkin.cs b/osu.Game/Skinning/RulesetResourcesSkin.cs new file mode 100644 index 0000000000..1905a8a899 --- /dev/null +++ b/osu.Game/Skinning/RulesetResourcesSkin.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.OpenGL.Textures; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using osu.Framework.Platform; +using osu.Game.Audio; +using osu.Game.Rulesets; + +namespace osu.Game.Skinning +{ + /// + /// An providing the resources of the ruleset for accessibility during lookups. + /// + public class RulesetResourcesSkin : ISkin + { + private readonly TextureStore rulesetTextures; + private readonly ISampleStore rulesetSamples; + + public RulesetResourcesSkin(Ruleset ruleset, GameHost host, AudioManager audio) + { + IResourceStore rulesetResources = ruleset.CreateResourceStore(); + + rulesetTextures = new TextureStore(host.CreateTextureLoaderStore(new NamespacedResourceStore(rulesetResources, @"Textures"))); + rulesetSamples = audio.GetSampleStore(new NamespacedResourceStore(rulesetResources, @"Samples")); + } + + public Drawable GetDrawableComponent(ISkinComponent component) => null; + + public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => rulesetTextures.Get(componentName, wrapModeS, wrapModeT); + + public ISample GetSample(ISampleInfo sampleInfo) + { + foreach (var lookup in sampleInfo.LookupNames) + { + ISample sample = rulesetSamples.Get(lookup); + if (sample != null) + return sample; + } + + return null; + } + + public IBindable GetConfig(TLookup lookup) => null; + } +} diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 8087043230..3d11b58a01 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -3,8 +3,10 @@ using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -35,6 +37,12 @@ namespace osu.Game.Skinning }; } + [Resolved] + private GameHost host { get; set; } + + [Resolved] + private AudioManager audio { get; set; } + [Resolved] private SkinManager skinManager { get; set; } @@ -60,6 +68,8 @@ namespace osu.Game.Skinning SkinSources.Add(Ruleset.CreateLegacySkinProvider(skinManager.DefaultLegacySkin, Beatmap)); SkinSources.Add(Ruleset.CreateLegacySkinProvider(skinManager.DefaultSkin, Beatmap)); + + SkinSources.Add(new RulesetResourcesSkin(Ruleset, host, audio)); } } } From ca3c45363a8d7c20b6e42c5676f38c7fb97b4515 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 10 Jun 2021 23:59:59 +0300 Subject: [PATCH 006/119] Add test coverage --- .../TestSceneRulesetSkinProvidingContainer.cs | 60 +++++++++++++++++++ .../Testing/TestSceneRulesetDependencies.cs | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs new file mode 100644 index 0000000000..41f1465c90 --- /dev/null +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -0,0 +1,60 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.OpenGL.Textures; +using osu.Framework.Graphics.Textures; +using osu.Game.Audio; +using osu.Game.Rulesets; +using osu.Game.Skinning; +using osu.Game.Tests.Testing; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Rulesets +{ + public class TestSceneRulesetSkinProvidingContainer : OsuTestScene + { + private RulesetSkinProvidingContainer rulesetSkinProvider; + private SkinRequester requester; + + protected override Ruleset CreateRuleset() => new TestSceneRulesetDependencies.TestRuleset(); + + [SetUp] + public void SetUp() => Schedule(() => + { + Child = rulesetSkinProvider = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin) + .WithChild(requester = new SkinRequester()); + }); + + [Test] + public void TestRulesetResources() + { + AddAssert("ruleset texture retrieved via skin", () => requester.GetTexture("test-image") != null); + AddAssert("ruleset sample retrieved via skin", () => requester.GetSample(new SampleInfo("test-sample")) != null); + } + + private class SkinRequester : Drawable, ISkin + { + private ISkinSource skin; + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + this.skin = skin; + } + + public Drawable GetDrawableComponent(ISkinComponent component) => skin.GetDrawableComponent(component); + + public Texture GetTexture(string componentName, WrapMode wrapModeS = default, WrapMode wrapModeT = default) => skin.GetTexture(componentName); + + public ISample GetSample(ISampleInfo sampleInfo) => skin.GetSample(sampleInfo); + + public IBindable GetConfig(TLookup lookup) => skin.GetConfig(lookup); + } + } +} diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 97087e31ab..fb50da32f3 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Testing Dependencies.Get() != null); } - private class TestRuleset : Ruleset + public class TestRuleset : Ruleset { public override string Description => string.Empty; public override string ShortName => string.Empty; From fe48ce4bd5d80ec5b039a5a88a7fa5df9fcfa749 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 11 Jun 2021 00:58:05 +0300 Subject: [PATCH 007/119] Remove unaccessed field It was a warning... --- .../Rulesets/TestSceneRulesetSkinProvidingContainer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs index 41f1465c90..e9f9766725 100644 --- a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -19,7 +19,6 @@ namespace osu.Game.Tests.Rulesets { public class TestSceneRulesetSkinProvidingContainer : OsuTestScene { - private RulesetSkinProvidingContainer rulesetSkinProvider; private SkinRequester requester; protected override Ruleset CreateRuleset() => new TestSceneRulesetDependencies.TestRuleset(); @@ -27,7 +26,7 @@ namespace osu.Game.Tests.Rulesets [SetUp] public void SetUp() => Schedule(() => { - Child = rulesetSkinProvider = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin) + Child = new RulesetSkinProvidingContainer(Ruleset.Value.CreateInstance(), Beatmap.Value.Beatmap, Beatmap.Value.Skin) .WithChild(requester = new SkinRequester()); }); From 1c67ef7c9190ae8bdfe36cce0ed6d6e5576b040c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 16:23:59 +0900 Subject: [PATCH 008/119] Make catchup clock support seeking --- .../Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs index 9e1a020eca..20d12d62a3 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs @@ -34,7 +34,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public void Stop() => IsRunning = false; - public bool Seek(double position) => true; + public bool Seek(double position) + { + CurrentTime = position; + return true; + } public void ResetSpeedAdjustments() { From 75d825c85cb01be1a55e56e8a2adfb1dd745c4db Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 16:24:52 +0900 Subject: [PATCH 009/119] Dont control master clock from sync manager --- .../Multiplayer/Spectate/CatchUpSyncManager.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs index efc12eaaa5..2d0e88238d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs @@ -63,7 +63,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate } updateCatchup(); - updateMasterClock(); } /// @@ -133,21 +132,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate } } } - - /// - /// Updates the master clock's running state. - /// - private void updateMasterClock() - { - bool anyInSync = playerClocks.Any(s => !s.IsCatchingUp); - - if (MasterClock.IsRunning != anyInSync) - { - if (anyInSync) - MasterClock.Start(); - else - MasterClock.Stop(); - } - } } } From a99cb79738f61d4cacbbda13c9b87283fba04733 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 16:25:45 +0900 Subject: [PATCH 010/119] Seek master clock on multi-spectator start --- .../Multiplayer/Spectate/CatchUpSyncManager.cs | 13 +++++++++++-- .../Multiplayer/Spectate/ISyncManager.cs | 6 ++++++ .../Multiplayer/Spectate/MultiSpectatorScreen.cs | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs index 2d0e88238d..0f7466e44b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -33,6 +34,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// public IAdjustableClock MasterClock { get; } + public event Action ReadyToStart; + /// /// The player clocks. /// @@ -80,14 +83,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate int readyCount = playerClocks.Count(s => !s.WaitingOnFrames.Value); if (readyCount == playerClocks.Count) - return hasStarted = true; + return performStart(); if (readyCount > 0) { firstStartAttemptTime ??= Time.Current; if (Time.Current - firstStartAttemptTime > MAXIMUM_START_DELAY) - return hasStarted = true; + return performStart(); + } + + bool performStart() + { + ReadyToStart?.Invoke(); + return hasStarted = true; } return false; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs index bd698108f6..f59c1a75f7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Timing; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate @@ -15,6 +16,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// IAdjustableClock MasterClock { get; } + /// + /// An event which is invoked when gameplay is ready to start. + /// + event Action ReadyToStart; + /// /// Adds an to manage. /// diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 983daac909..e401c45933 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -101,6 +101,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, leaderboardContainer.Add); + + syncManager.ReadyToStart += onReadyToStart; } protected override void LoadComplete() @@ -129,6 +131,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private bool isCandidateAudioSource([CanBeNull] ISpectatorPlayerClock clock) => clock?.IsRunning == true && !clock.IsCatchingUp && !clock.WaitingOnFrames.Value; + private void onReadyToStart() + { + var startTime = instances.Where(i => i.Score != null) + .SelectMany(i => i.Score.Replay.Frames) + .Select(f => f.Time) + .DefaultIfEmpty(0) + .Max(); + + masterClockContainer.Seek(startTime); + masterClockContainer.Start(); + } + protected override void OnUserStateChanged(int userId, SpectatorState spectatorState) { } From 9eaaac6bb790616db3dcb259669e2b5d48b74b39 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 17:59:27 +0900 Subject: [PATCH 011/119] Remove master clock state assertions --- .../OnlinePlay/TestSceneCatchUpSyncManager.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs b/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs index d4e591cf09..6851df3832 100644 --- a/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs +++ b/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs @@ -31,32 +31,24 @@ namespace osu.Game.Tests.OnlinePlay } [Test] - public void TestMasterClockStartsWhenAllPlayerClocksHaveFrames() + public void TestPlayerClocksStartWhenAllHaveFrames() { setWaiting(() => player1, false); - assertMasterState(false); assertPlayerClockState(() => player1, false); assertPlayerClockState(() => player2, false); setWaiting(() => player2, false); - assertMasterState(true); assertPlayerClockState(() => player1, true); assertPlayerClockState(() => player2, true); } [Test] - public void TestMasterClockDoesNotStartWhenNoneReadyForMaximumDelayTime() - { - AddWaitStep($"wait {CatchUpSyncManager.MAXIMUM_START_DELAY} milliseconds", (int)Math.Ceiling(CatchUpSyncManager.MAXIMUM_START_DELAY / TimePerAction)); - assertMasterState(false); - } - - [Test] - public void TestMasterClockStartsWhenAnyReadyForMaximumDelayTime() + public void TestReadyPlayersStartWhenReadyForMaximumDelayTime() { setWaiting(() => player1, false); AddWaitStep($"wait {CatchUpSyncManager.MAXIMUM_START_DELAY} milliseconds", (int)Math.Ceiling(CatchUpSyncManager.MAXIMUM_START_DELAY / TimePerAction)); - assertMasterState(true); + assertPlayerClockState(() => player1, true); + assertPlayerClockState(() => player2, false); } [Test] @@ -153,9 +145,6 @@ namespace osu.Game.Tests.OnlinePlay private void setPlayerClockTime(Func playerClock, double offsetFromMaster) => AddStep($"set player clock {playerClock().Id} = master - {offsetFromMaster}", () => playerClock().Seek(master.CurrentTime - offsetFromMaster)); - private void assertMasterState(bool running) - => AddAssert($"master clock {(running ? "is" : "is not")} running", () => master.IsRunning == running); - private void assertCatchingUp(Func playerClock, bool catchingUp) => AddAssert($"player clock {playerClock().Id} {(catchingUp ? "is" : "is not")} catching up", () => playerClock().IsCatchingUp == catchingUp); @@ -201,6 +190,11 @@ namespace osu.Game.Tests.OnlinePlay private class TestManualClock : ManualClock, IAdjustableClock { + public TestManualClock() + { + IsRunning = true; + } + public void Start() => IsRunning = true; public void Stop() => IsRunning = false; From e9ebbd298d4c7129123e40c1f8b8352abfd9ed96 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 18:13:54 +0900 Subject: [PATCH 012/119] Add a few more tests --- .../TestSceneMultiSpectatorScreen.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index f5032fc2a5..35d096a92e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -12,6 +12,7 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.Spectator; +using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; @@ -224,6 +225,36 @@ namespace osu.Game.Tests.Visual.Multiplayer assertMuted(PLAYER_2_ID, true); } + [Test] + public void TestSpectatingDuringGameplay() + { + var players = new[] { PLAYER_1_ID, PLAYER_2_ID }; + + start(players); + sendFrames(players, 300); + + loadSpectateScreen(); + sendFrames(players, 300); + + AddUntilStep("playing from correct point in time", () => this.ChildrenOfType().All(r => r.FrameStableClock.CurrentTime > 30000)); + } + + [Test] + public void TestSpectatingDuringGameplayWithLateFrames() + { + start(new[] { PLAYER_1_ID, PLAYER_2_ID }); + sendFrames(new[] { PLAYER_1_ID, PLAYER_2_ID }, 300); + + loadSpectateScreen(); + sendFrames(PLAYER_1_ID, 300); + + AddWaitStep("wait maximum start delay seconds", (int)(CatchUpSyncManager.MAXIMUM_START_DELAY / TimePerAction)); + checkPaused(PLAYER_1_ID, false); + + sendFrames(PLAYER_2_ID, 300); + AddUntilStep("player 2 playing from correct point in time", () => getPlayer(PLAYER_2_ID).ChildrenOfType().Single().FrameStableClock.CurrentTime > 30000); + } + private void loadSpectateScreen(bool waitForPlayerLoad = true) { AddStep("load screen", () => From 263b8ff097ed688e3fe0ff6e9bb90d1a17c93057 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 18:14:37 +0900 Subject: [PATCH 013/119] Wait for full player load --- osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs index fe79e5db72..95ccc08608 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Whether a is loaded in the area. /// - public bool PlayerLoaded => stack?.CurrentScreen is Player; + public bool PlayerLoaded => (stack?.CurrentScreen as Player)?.IsLoaded == true; /// /// The user id this corresponds to. From 59eda70c12204f0ed71a551d711d1bb7aa1adbb3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 18:39:50 +0900 Subject: [PATCH 014/119] Seek to the least most-recent frame instead --- .../OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index e401c45933..1ea63e454a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -133,11 +133,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private void onReadyToStart() { + // 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. var startTime = instances.Where(i => i.Score != null) .SelectMany(i => i.Score.Replay.Frames) .Select(f => f.Time) .DefaultIfEmpty(0) - .Max(); + .Min(); masterClockContainer.Seek(startTime); masterClockContainer.Start(); From 0a8daab4f78e369481e4bff7c382e2bd845386fd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 19:15:53 +0900 Subject: [PATCH 015/119] Pause master clock when too far ahead --- .../TestSceneMultiSpectatorScreen.cs | 17 +++++++++++++++ .../Spectate/CatchUpSyncManager.cs | 21 ++++++++++++++++--- .../Multiplayer/Spectate/ISyncManager.cs | 10 +++++++-- .../Multiplayer/Spectate/MasterClockState.cs | 18 ++++++++++++++++ .../Spectate/MultiSpectatorScreen.cs | 10 +++++++++ 5 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 35d096a92e..18eb7e1c1e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -103,6 +103,23 @@ namespace osu.Game.Tests.Visual.Multiplayer AddWaitStep("wait a bit", 20); } + [Test] + public void TestTimeDoesNotProgressWhileAllPlayersPaused() + { + start(new[] { PLAYER_1_ID, PLAYER_2_ID }); + loadSpectateScreen(); + + sendFrames(PLAYER_1_ID, 20); + sendFrames(PLAYER_2_ID, 10); + + checkPaused(PLAYER_2_ID, true); + checkPausedInstant(PLAYER_1_ID, false); + AddAssert("master clock still running", () => this.ChildrenOfType().Single().IsRunning); + + checkPaused(PLAYER_1_ID, true); + AddUntilStep("master clock paused", () => !this.ChildrenOfType().Single().IsRunning); + } + [Test] public void TestPlayersMustStartSimultaneously() { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs index 0f7466e44b..781123f5bb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Timing; @@ -29,18 +30,22 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// public const double MAXIMUM_START_DELAY = 15000; + public event Action ReadyToStart; + /// /// The master clock which is used to control the timing of all player clocks clocks. /// public IAdjustableClock MasterClock { get; } - public event Action ReadyToStart; + public IBindable MasterState => masterState; /// /// The player clocks. /// private readonly List playerClocks = new List(); + private readonly Bindable masterState = new Bindable(); + private bool hasStarted; private double? firstStartAttemptTime; @@ -65,7 +70,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate return; } - updateCatchup(); + updatePlayerCatchup(); + updateMasterState(); } /// @@ -105,7 +111,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// /// Updates the catchup states of all player clocks clocks. /// - private void updateCatchup() + private void updatePlayerCatchup() { for (int i = 0; i < playerClocks.Count; i++) { @@ -141,5 +147,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate } } } + + /// + /// Updates the state of the master clock. + /// + private void updateMasterState() + { + bool anyInSync = playerClocks.Any(s => !s.IsCatchingUp); + masterState.Value = anyInSync ? MasterClockState.Synchronised : MasterClockState.TooFarAhead; + } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs index f59c1a75f7..3c644ccb78 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Timing; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate @@ -11,15 +12,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// public interface ISyncManager { + /// + /// An event which is invoked when gameplay is ready to start. + /// + event Action ReadyToStart; + /// /// The master clock which player clocks should synchronise to. /// IAdjustableClock MasterClock { get; } /// - /// An event which is invoked when gameplay is ready to start. + /// An event which is invoked when the state of is changed. /// - event Action ReadyToStart; + IBindable MasterState { get; } /// /// Adds an to manage. diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs new file mode 100644 index 0000000000..8982d1669d --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate +{ + public enum MasterClockState + { + /// + /// The master clock is synchronised with at least one player clock. + /// + Synchronised, + + /// + /// The master clock is too far ahead of any player clock and needs to slow down. + /// + TooFarAhead + } +} diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 1ea63e454a..ee1968aa5f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; @@ -103,6 +104,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate }, leaderboardContainer.Add); syncManager.ReadyToStart += onReadyToStart; + syncManager.MasterState.BindValueChanged(onMasterStateChanged, true); } protected override void LoadComplete() @@ -145,6 +147,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate masterClockContainer.Start(); } + private void onMasterStateChanged(ValueChangedEvent state) + { + if (state.NewValue == MasterClockState.Synchronised) + masterClockContainer.Start(); + else + masterClockContainer.Stop(); + } + protected override void OnUserStateChanged(int userId, SpectatorState spectatorState) { } From 9f163f7f20ca155ab331d63d2fae99fdb1c2591d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 11 Jun 2021 19:23:25 +0900 Subject: [PATCH 016/119] Use switch statement to be more explicit about state --- .../Multiplayer/Spectate/MultiSpectatorScreen.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index ee1968aa5f..013e5551cf 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -149,10 +149,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private void onMasterStateChanged(ValueChangedEvent state) { - if (state.NewValue == MasterClockState.Synchronised) - masterClockContainer.Start(); - else - masterClockContainer.Stop(); + switch (state.NewValue) + { + case MasterClockState.Synchronised: + masterClockContainer.Start(); + break; + + case MasterClockState.TooFarAhead: + masterClockContainer.Stop(); + break; + } } protected override void OnUserStateChanged(int userId, SpectatorState spectatorState) From ee84364d7ca7eea57d37257c198694ec08d6fb80 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 22 Jun 2021 20:38:24 +0300 Subject: [PATCH 017/119] Resolve conflict issues --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 4a4773fce4..e46ba6d857 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -51,7 +51,6 @@ namespace osu.Game.Skinning private AudioManager audio { get; set; } [Resolved] - private SkinManager skinManager { get; set; } private ISkinSource skinSource { get; set; } [BackgroundDependencyLoader] @@ -84,6 +83,8 @@ namespace osu.Game.Skinning break; } } + + SkinSources.Add(new RulesetResourcesSkin(Ruleset, host, audio)); } protected ISkin GetLegacyRulesetTransformedSkin(ISkin legacySkin) @@ -102,9 +103,6 @@ namespace osu.Game.Skinning { base.Dispose(isDisposing); - SkinSources.Add(Ruleset.CreateLegacySkinProvider(skinManager.DefaultSkin, Beatmap)); - - SkinSources.Add(new RulesetResourcesSkin(Ruleset, host, audio)); if (skinSource != null) skinSource.SourceChanged -= OnSourceChanged; } From 0db06c727b47c43b0207af22054a26c774c8c5b9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 23 Jun 2021 09:41:45 +0300 Subject: [PATCH 018/119] Dispose resource stores on finalizer --- osu.Game/Skinning/RulesetResourcesSkin.cs | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/osu.Game/Skinning/RulesetResourcesSkin.cs b/osu.Game/Skinning/RulesetResourcesSkin.cs index 1905a8a899..60b22a8e67 100644 --- a/osu.Game/Skinning/RulesetResourcesSkin.cs +++ b/osu.Game/Skinning/RulesetResourcesSkin.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; @@ -47,5 +48,34 @@ namespace osu.Game.Skinning } public IBindable GetConfig(TLookup lookup) => null; + + #region Disposal + + ~RulesetResourcesSkin() + { + // required to potentially clean up sample store from audio hierarchy. + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private bool isDisposed; + + protected virtual void Dispose(bool isDisposing) + { + if (isDisposed) + return; + + isDisposed = true; + + rulesetTextures?.Dispose(); + rulesetSamples?.Dispose(); + } + + #endregion } } From 2e6800f5862f1815727b967a444f951fdbc89c1f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 23 Jun 2021 09:52:00 +0300 Subject: [PATCH 019/119] Enable NRT in `RulesetResourcesSkin` --- osu.Game/Skinning/RulesetResourcesSkin.cs | 29 +++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/osu.Game/Skinning/RulesetResourcesSkin.cs b/osu.Game/Skinning/RulesetResourcesSkin.cs index 60b22a8e67..5cf2eec338 100644 --- a/osu.Game/Skinning/RulesetResourcesSkin.cs +++ b/osu.Game/Skinning/RulesetResourcesSkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using System; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -20,26 +22,29 @@ namespace osu.Game.Skinning /// public class RulesetResourcesSkin : ISkin { - private readonly TextureStore rulesetTextures; - private readonly ISampleStore rulesetSamples; + private readonly TextureStore? textures; + private readonly ISampleStore? samples; public RulesetResourcesSkin(Ruleset ruleset, GameHost host, AudioManager audio) { - IResourceStore rulesetResources = ruleset.CreateResourceStore(); + IResourceStore? resources = ruleset.CreateResourceStore(); - rulesetTextures = new TextureStore(host.CreateTextureLoaderStore(new NamespacedResourceStore(rulesetResources, @"Textures"))); - rulesetSamples = audio.GetSampleStore(new NamespacedResourceStore(rulesetResources, @"Samples")); + if (resources != null) + { + textures = new TextureStore(host.CreateTextureLoaderStore(new NamespacedResourceStore(resources, @"Textures"))); + samples = audio.GetSampleStore(new NamespacedResourceStore(resources, @"Samples")); + } } - public Drawable GetDrawableComponent(ISkinComponent component) => null; + public Drawable? GetDrawableComponent(ISkinComponent component) => null; - public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => rulesetTextures.Get(componentName, wrapModeS, wrapModeT); + public Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => textures?.Get(componentName, wrapModeS, wrapModeT); - public ISample GetSample(ISampleInfo sampleInfo) + public ISample? GetSample(ISampleInfo sampleInfo) { foreach (var lookup in sampleInfo.LookupNames) { - ISample sample = rulesetSamples.Get(lookup); + ISample? sample = samples?.Get(lookup); if (sample != null) return sample; } @@ -47,7 +52,7 @@ namespace osu.Game.Skinning return null; } - public IBindable GetConfig(TLookup lookup) => null; + public IBindable? GetConfig(TLookup lookup) => null; #region Disposal @@ -72,8 +77,8 @@ namespace osu.Game.Skinning isDisposed = true; - rulesetTextures?.Dispose(); - rulesetSamples?.Dispose(); + textures?.Dispose(); + samples?.Dispose(); } #endregion From 53fa22988097e9f22d6b16f8de7ce512a1a1bbab Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 23 Jun 2021 10:09:25 +0300 Subject: [PATCH 020/119] Add ruleset resources skin before `SkinManager.DefaultSkin` --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index e46ba6d857..c117df4b09 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -50,6 +50,9 @@ namespace osu.Game.Skinning [Resolved] private AudioManager audio { get; set; } + [Resolved] + private SkinManager skinManager { get; set; } + [Resolved] private ISkinSource skinSource { get; set; } @@ -84,7 +87,7 @@ namespace osu.Game.Skinning } } - SkinSources.Add(new RulesetResourcesSkin(Ruleset, host, audio)); + SkinSources.Insert(SkinSources.IndexOf(skinManager.DefaultSkin), new RulesetResourcesSkin(Ruleset, host, audio)); } protected ISkin GetLegacyRulesetTransformedSkin(ISkin legacySkin) From d48446990616a5d10c81b35a4aa4470283dc5757 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 23 Jun 2021 10:44:21 +0300 Subject: [PATCH 021/119] Handle case where `SkinManager` sources aren't part of `AllSources` In tests. --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index c117df4b09..83e2d398f9 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -87,7 +87,11 @@ namespace osu.Game.Skinning } } - SkinSources.Insert(SkinSources.IndexOf(skinManager.DefaultSkin), new RulesetResourcesSkin(Ruleset, host, audio)); + var defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); + if (defaultSkinIndex >= 0) + SkinSources.Insert(defaultSkinIndex, new RulesetResourcesSkin(Ruleset, host, audio)); + else + SkinSources.Add(new RulesetResourcesSkin(Ruleset, host, audio)); } protected ISkin GetLegacyRulesetTransformedSkin(ISkin legacySkin) From c9ec4b9da46bb1692fa86a5650e8efe8bbedcb95 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 00:28:39 +0900 Subject: [PATCH 022/119] Remove RoomTestScene inheritance from simple test scenes --- .../Multiplayer/TestSceneLoungeRoomInfo.cs | 34 +++---- .../TestSceneMatchBeatmapDetailArea.cs | 23 +++-- .../Multiplayer/TestSceneMatchHeader.cs | 71 +++++++------ .../Multiplayer/TestSceneMatchLeaderboard.cs | 99 ++++++++++--------- .../TestSceneMultiplayerMatchSongSelect.cs | 2 +- .../TestSceneMultiplayerRoomManager.cs | 2 +- .../TestScenePlaylistsMatchSettingsOverlay.cs | 32 +++--- .../TestScenePlaylistsParticipantsList.cs | 17 ++-- osu.Game/Tests/Visual/TestRoomContainer.cs | 38 +++++++ 9 files changed, 190 insertions(+), 128 deletions(-) create mode 100644 osu.Game/Tests/Visual/TestRoomContainer.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs index 9f24347ae9..a8cbd8b7ef 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs @@ -10,28 +10,28 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneLoungeRoomInfo : RoomTestScene + public class TestSceneLoungeRoomInfo : OsuTestScene { + private TestRoomContainer roomContainer; + [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - Child = new RoomInfo + Child = roomContainer = new TestRoomContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 500 + Child = new RoomInfo + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500 + } }; }); - public override void SetUpSteps() - { - // Todo: Temp - } - [Test] public void TestNonSelectedRoom() { - AddStep("set null room", () => Room.RoomID.Value = null); + AddStep("set null room", () => roomContainer.Room.RoomID.Value = null); } [Test] @@ -39,11 +39,11 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("set open room", () => { - Room.RoomID.Value = 0; - Room.Name.Value = "Room 0"; - Room.Host.Value = new User { Username = "peppy", Id = 2 }; - Room.EndDate.Value = DateTimeOffset.Now.AddMonths(1); - Room.Status.Value = new RoomStatusOpen(); + roomContainer.Room.RoomID.Value = 0; + roomContainer.Room.Name.Value = "Room 0"; + roomContainer.Room.Host.Value = new User { Username = "peppy", Id = 2 }; + roomContainer.Room.EndDate.Value = DateTimeOffset.Now.AddMonths(1); + roomContainer.Room.Status.Value = new RoomStatusOpen(); }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 9ad9f2c883..2a254b1573 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchBeatmapDetailArea : RoomTestScene + public class TestSceneMatchBeatmapDetailArea : OsuTestScene { [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -23,23 +23,28 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private RulesetStore rulesetStore { get; set; } + private TestRoomContainer roomContainer; + [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - Child = new MatchBeatmapDetailArea + Child = roomContainer = new TestRoomContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500), - CreateNewItem = createNewItem + Child = new MatchBeatmapDetailArea + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500), + CreateNewItem = createNewItem + } }; }); private void createNewItem() { - Room.Playlist.Add(new PlaylistItem + roomContainer.Room.Playlist.Add(new PlaylistItem { - ID = Room.Playlist.Count, + ID = roomContainer.Room.Playlist.Count, Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo }, RequiredMods = diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index 7cdc6b1a7d..50e6426472 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -11,42 +11,51 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchHeader : RoomTestScene + public class TestSceneMatchHeader : OsuTestScene { - public TestSceneMatchHeader() - { - Child = new Header(); - } + private TestRoomContainer roomContainer; [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - Room.Playlist.Add(new PlaylistItem + Child = roomContainer = new TestRoomContainer { - Beatmap = - { - Value = new BeatmapInfo - { - Metadata = new BeatmapMetadata - { - Title = "Title", - Artist = "Artist", - AuthorString = "Author", - }, - Version = "Version", - Ruleset = new OsuRuleset().RulesetInfo - } - }, - RequiredMods = - { - new OsuModDoubleTime(), - new OsuModNoFail(), - new OsuModRelax(), - } - }); - - Room.Name.Value = "A very awesome room"; - Room.Host.Value = new User { Id = 2, Username = "peppy" }; + Child = new Header() + }; }); + + [Test] + public void TestBasicRoom() + { + AddStep("set basic room", () => + { + roomContainer.Room.Playlist.Add(new PlaylistItem + { + Beatmap = + { + Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = "Title", + Artist = "Artist", + AuthorString = "Author", + }, + Version = "Version", + Ruleset = new OsuRuleset().RulesetInfo + } + }, + RequiredMods = + { + new OsuModDoubleTime(), + new OsuModNoFail(), + new OsuModRelax(), + } + }); + + roomContainer.Room.Name.Value = "A very awesome room"; + roomContainer.Room.Host.Value = new User { Id = 2, Username = "peppy" }; + }); + } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 64eaf0556b..566dc9fc00 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -2,72 +2,75 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using Newtonsoft.Json; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Users; using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchLeaderboard : RoomTestScene + public class TestSceneMatchLeaderboard : OsuTestScene { - protected override bool UseOnlineAPI => true; - - public TestSceneMatchLeaderboard() - { - Add(new MatchLeaderboard - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(550f, 450f), - Scope = MatchLeaderboardScope.Overall, - }); - } - [BackgroundDependencyLoader] - private void load(IAPIProvider api) + private void load() { - var req = new GetRoomScoresRequest(); - req.Success += v => { }; - req.Failure += _ => { }; + ((DummyAPIAccess)API).HandleRequest = r => + { + switch (r) + { + case GetRoomLeaderboardRequest leaderboardRequest: + leaderboardRequest.TriggerSuccess(new APILeaderboard + { + Leaderboard = new List + { + new APIUserScoreAggregate + { + UserID = 2, + User = new User { Id = 2, Username = "peppy" }, + TotalScore = 995533, + RoomID = 3, + CompletedBeatmaps = 1, + TotalAttempts = 6, + Accuracy = 0.9851 + }, + new APIUserScoreAggregate + { + UserID = 1040328, + User = new User { Id = 1040328, Username = "smoogipoo" }, + TotalScore = 981100, + RoomID = 3, + CompletedBeatmaps = 1, + TotalAttempts = 9, + Accuracy = 0.937 + } + } + }); + return true; + } - api.Queue(req); + return false; + }; } [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - Room.RoomID.Value = 3; + Child = new TestRoomContainer + { + Room = { RoomID = { Value = 3 } }, + Child = new MatchLeaderboard + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(550f, 450f), + Scope = MatchLeaderboardScope.Overall, + } + }; }); - - private class GetRoomScoresRequest : APIRequest> - { - protected override string Target => "rooms/3/leaderboard"; - } - - private class RoomScore - { - [JsonProperty("user")] - public User User { get; set; } - - [JsonProperty("accuracy")] - public double Accuracy { get; set; } - - [JsonProperty("total_score")] - public int TotalScore { get; set; } - - [JsonProperty("pp")] - public double PP { get; set; } - - [JsonProperty("attempts")] - public int TotalAttempts { get; set; } - - [JsonProperty("completed")] - public int CompletedAttempts { get; set; } - } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index 5b059c06f5..2725ef5976 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -29,7 +29,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchSongSelect : RoomTestScene + public class TestSceneMultiplayerMatchSongSelect : ScreenTestScene { private BeatmapManager manager; private RulesetStore rulesets; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index c008771fd9..80e36916b1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -12,7 +12,7 @@ using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual.Multiplayer { [HeadlessTest] - public class TestSceneMultiplayerRoomManager : RoomTestScene + public class TestSceneMultiplayerRoomManager : OsuTestScene { private TestMultiplayerRoomContainer roomContainer; private TestMultiplayerRoomManager roomManager => roomContainer.RoomManager; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 44a79b6598..3055a2c6c7 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -15,23 +15,25 @@ using osu.Game.Screens.OnlinePlay.Playlists; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsMatchSettingsOverlay : RoomTestScene + public class TestScenePlaylistsMatchSettingsOverlay : OsuTestScene { [Cached(Type = typeof(IRoomManager))] private TestRoomManager roomManager = new TestRoomManager(); + private TestRoomContainer roomContainer; private TestRoomSettings settings; [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - settings = new TestRoomSettings + Child = roomContainer = new TestRoomContainer { - RelativeSizeAxes = Axes.Both, - State = { Value = Visibility.Visible } + Child = settings = new TestRoomSettings + { + RelativeSizeAxes = Axes.Both, + State = { Value = Visibility.Visible } + } }; - - Child = settings; }); [Test] @@ -39,19 +41,19 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("clear name and beatmap", () => { - Room.Name.Value = ""; - Room.Playlist.Clear(); + roomContainer.Room.Name.Value = ""; + roomContainer.Room.Playlist.Clear(); }); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set name", () => Room.Name.Value = "Room name"); + AddStep("set name", () => roomContainer.Room.Name.Value = "Room name"); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } })); + AddStep("set beatmap", () => roomContainer.Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } })); AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value); - AddStep("clear name", () => Room.Name.Value = ""); + AddStep("clear name", () => roomContainer.Room.Name.Value = ""); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); } @@ -67,7 +69,7 @@ namespace osu.Game.Tests.Visual.Playlists { settings.NameField.Current.Value = expected_name; settings.DurationField.Current.Value = expectedDuration; - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); + roomContainer.Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); roomManager.CreateRequested = r => { @@ -88,8 +90,8 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("setup", () => { - Room.Name.Value = "Test Room"; - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); + roomContainer.Room.Name.Value = "Test Room"; + roomContainer.Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); fail = true; roomManager.CreateRequested = _ => !fail; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs index 255f147ec9..083930698f 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs @@ -8,16 +8,21 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsParticipantsList : RoomTestScene + public class TestScenePlaylistsParticipantsList : OsuTestScene { + private TestRoomContainer roomContainer; + [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - Room.RoomID.Value = 7; + Child = roomContainer = new TestRoomContainer + { + Room = { RoomID = { Value = 7 } } + }; for (int i = 0; i < 50; i++) { - Room.RecentParticipants.Add(new User + roomContainer.Room.RecentParticipants.Add(new User { Username = "peppy", Statistics = new UserStatistics { GlobalRank = 1234 }, @@ -31,7 +36,7 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("create component", () => { - Child = new ParticipantsDisplay(Direction.Horizontal) + roomContainer.Child = new ParticipantsDisplay(Direction.Horizontal) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -45,7 +50,7 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("create component", () => { - Child = new ParticipantsDisplay(Direction.Vertical) + roomContainer.Child = new ParticipantsDisplay(Direction.Vertical) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Tests/Visual/TestRoomContainer.cs b/osu.Game/Tests/Visual/TestRoomContainer.cs new file mode 100644 index 0000000000..c4af89cd51 --- /dev/null +++ b/osu.Game/Tests/Visual/TestRoomContainer.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Rooms; + +namespace osu.Game.Tests.Visual +{ + /// + /// Contains a that is resolvable by components in test scenes. + /// + public class TestRoomContainer : Container + { + /// + /// The cached . + /// + public readonly Room Room = new Room(); + + [Cached] + private readonly Bindable roomBindable; + + public TestRoomContainer() + { + RelativeSizeAxes = Axes.Both; + roomBindable = new Bindable(Room); + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); + dependencies.Model.Value = Room; + return dependencies; + } + } +} From a98b5618b84e873adffeed23fdfd2a15a58a907c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 24 Jun 2021 10:07:38 +0300 Subject: [PATCH 023/119] Convert `RulesetResourcesSkin` to plain `ResourcesSkin` and pass non-null resources --- ...lesetResourcesSkin.cs => ResourcesSkin.cs} | 30 ++++++++----------- .../Skinning/RulesetSkinProvidingContainer.cs | 18 +++++++---- 2 files changed, 25 insertions(+), 23 deletions(-) rename osu.Game/Skinning/{RulesetResourcesSkin.cs => ResourcesSkin.cs} (61%) diff --git a/osu.Game/Skinning/RulesetResourcesSkin.cs b/osu.Game/Skinning/ResourcesSkin.cs similarity index 61% rename from osu.Game/Skinning/RulesetResourcesSkin.cs rename to osu.Game/Skinning/ResourcesSkin.cs index 5cf2eec338..3d17d7cc3d 100644 --- a/osu.Game/Skinning/RulesetResourcesSkin.cs +++ b/osu.Game/Skinning/ResourcesSkin.cs @@ -13,38 +13,32 @@ using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Audio; -using osu.Game.Rulesets; namespace osu.Game.Skinning { /// - /// An providing the resources of the ruleset for accessibility during lookups. + /// An that uses an underlying with namespaces for resources retrieval. /// - public class RulesetResourcesSkin : ISkin + public class ResourcesSkin : ISkin { - private readonly TextureStore? textures; - private readonly ISampleStore? samples; + private readonly TextureStore textures; + private readonly ISampleStore samples; - public RulesetResourcesSkin(Ruleset ruleset, GameHost host, AudioManager audio) + public ResourcesSkin(IResourceStore resources, GameHost host, AudioManager audio) { - IResourceStore? resources = ruleset.CreateResourceStore(); - - if (resources != null) - { - textures = new TextureStore(host.CreateTextureLoaderStore(new NamespacedResourceStore(resources, @"Textures"))); - samples = audio.GetSampleStore(new NamespacedResourceStore(resources, @"Samples")); - } + textures = new TextureStore(host.CreateTextureLoaderStore(new NamespacedResourceStore(resources, @"Textures"))); + samples = audio.GetSampleStore(new NamespacedResourceStore(resources, @"Samples")); } public Drawable? GetDrawableComponent(ISkinComponent component) => null; - public Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => textures?.Get(componentName, wrapModeS, wrapModeT); + public Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => textures.Get(componentName, wrapModeS, wrapModeT); public ISample? GetSample(ISampleInfo sampleInfo) { foreach (var lookup in sampleInfo.LookupNames) { - ISample? sample = samples?.Get(lookup); + ISample? sample = samples.Get(lookup); if (sample != null) return sample; } @@ -56,7 +50,7 @@ namespace osu.Game.Skinning #region Disposal - ~RulesetResourcesSkin() + ~ResourcesSkin() { // required to potentially clean up sample store from audio hierarchy. Dispose(false); @@ -77,8 +71,8 @@ namespace osu.Game.Skinning isDisposed = true; - textures?.Dispose(); - samples?.Dispose(); + textures.Dispose(); + samples.Dispose(); } #endregion diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 83e2d398f9..54bf91523f 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -87,11 +88,18 @@ namespace osu.Game.Skinning } } - var defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); - if (defaultSkinIndex >= 0) - SkinSources.Insert(defaultSkinIndex, new RulesetResourcesSkin(Ruleset, host, audio)); - else - SkinSources.Add(new RulesetResourcesSkin(Ruleset, host, audio)); + if (Ruleset.CreateResourceStore() is IResourceStore resources) + { + int defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); + + if (defaultSkinIndex >= 0) + SkinSources.Insert(defaultSkinIndex, new ResourcesSkin(resources, host, audio)); + else + { + // Tests may potentially override the SkinManager with another source that doesn't include it in AllSources. + SkinSources.Add(new ResourcesSkin(resources, host, audio)); + } + } } protected ISkin GetLegacyRulesetTransformedSkin(ISkin legacySkin) From 4af119a407c649e364fe917fa63049f52b5cb4a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 16:29:06 +0900 Subject: [PATCH 024/119] Re-namespace --- osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs | 1 + .../Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs | 1 + osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs | 1 + osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs | 1 + .../Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs | 1 + .../Visual/Playlists/TestScenePlaylistsParticipantsList.cs | 1 + osu.Game/Tests/Visual/{ => OnlinePlay}/TestRoomContainer.cs | 2 +- 7 files changed, 7 insertions(+), 1 deletion(-) rename osu.Game/Tests/Visual/{ => OnlinePlay}/TestRoomContainer.cs (96%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs index a8cbd8b7ef..73f7865208 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 2a254b1573..d114ae8abf 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual.OnlinePlay; using osuTK; namespace osu.Game.Tests.Visual.Multiplayer diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index 50e6426472..25cdfd4a90 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -7,6 +7,7 @@ using osu.Game.Online.Rooms; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.OnlinePlay.Match.Components; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 566dc9fc00..467df97cb9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -9,6 +9,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Match.Components; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; using osuTK; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 3055a2c6c7..94aed2ecfa 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Playlists; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Playlists { diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs index 083930698f..02ddfe4e79 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; namespace osu.Game.Tests.Visual.Playlists diff --git a/osu.Game/Tests/Visual/TestRoomContainer.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs similarity index 96% rename from osu.Game/Tests/Visual/TestRoomContainer.cs rename to osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs index c4af89cd51..93dc836d23 100644 --- a/osu.Game/Tests/Visual/TestRoomContainer.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Rooms; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.OnlinePlay { /// /// Contains a that is resolvable by components in test scenes. From 9287fae5f764610063e19976986d5b753e39f786 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 16:54:09 +0900 Subject: [PATCH 025/119] Simplify --- osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs index 93dc836d23..c2abcdfd08 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs @@ -19,19 +19,18 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// public readonly Room Room = new Room(); - [Cached] - private readonly Bindable roomBindable; - public TestRoomContainer() { RelativeSizeAxes = Axes.Both; - roomBindable = new Bindable(Room); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - var dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); - dependencies.Model.Value = Room; + var dependencies = new DependencyContainer( + new CachedModelDependencyContainer(parent) { Model = { Value = Room } }); + + dependencies.Cache(new Bindable(Room)); + return dependencies; } } From a7b5c3bed124798ed1a9b46ff391bd4df63337cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 17:01:28 +0900 Subject: [PATCH 026/119] Add OnlinePlaySubScreenTestScene --- .../TestScenePlaylistsSongSelect.cs | 3 +- .../TestScenePlaylistsRoomSubScreen.cs | 3 +- .../OnlinePlaySubScreenTestScene.cs | 64 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index d95a95ebe5..b958afd183 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -20,10 +20,11 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Playlists; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestScenePlaylistsSongSelect : RoomTestScene + public class TestScenePlaylistsSongSelect : OnlinePlaySubScreenTestScene { [Resolved] private BeatmapManager beatmapManager { get; set; } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index a08a91314b..73f9fcd8fd 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -19,12 +19,13 @@ using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsRoomSubScreen : RoomTestScene + public class TestScenePlaylistsRoomSubScreen : OnlinePlaySubScreenTestScene { [Cached(typeof(IRoomManager))] private readonly TestRoomManager roomManager = new TestRoomManager(); diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs new file mode 100644 index 0000000000..27cb6496ce --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Online.Rooms; +using osu.Game.Screens; +using osu.Game.Screens.OnlinePlay; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + public abstract class OnlinePlaySubScreenTestScene : ScreenTestScene + { + /// + /// The cached . + /// + protected Room Room { get; private set; } + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("create dependencies", () => LoadScreen(new DependenciesScreen(CreateScreenDependencies))); + } + + /// + /// Creates dependencies for any pushed via . + /// Invoked at the start of every test via . + /// + /// + /// This should be overridden to add any custom dependencies required by subclasses of . + /// + /// The parent dependency container. + /// The resultant dependency container. + protected virtual IReadOnlyDependencyContainer CreateScreenDependencies(IReadOnlyDependencyContainer parent) + { + Room = new Room(); + + var dependencies = new DependencyContainer( + new CachedModelDependencyContainer(parent) { Model = { Value = Room } }); + + dependencies.Cache(new Bindable(Room)); + + return dependencies; + } + + /// + /// A dummy screen used for injecting new dependencies into the hierarchy before any screen is pushed via . + /// + private class DependenciesScreen : OsuScreen + { + private readonly Func createDependenciesFunc; + + public DependenciesScreen(Func createDependenciesFunc) + { + this.createDependenciesFunc = createDependenciesFunc; + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + => createDependenciesFunc(base.CreateChildDependencies(parent)); + } + } +} From 5115299e9aa3fc7119dfa12784c1bee4a034ddb9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 19:09:31 +0900 Subject: [PATCH 027/119] Merge RoomManagerTestScene into OnlinePlaySubScreenTestScene --- .../Multiplayer/RoomManagerTestScene.cs | 61 ------------ .../Visual/Multiplayer/TestRoomManager.cs | 35 ------- .../TestSceneLoungeRoomsContainer.cs | 17 ++-- .../TestScenePlaylistsSongSelect.cs | 24 ++--- .../TestScenePlaylistsLoungeSubScreen.cs | 6 +- .../TestScenePlaylistsRoomSubScreen.cs | 58 +++-------- .../OnlinePlaySubScreenTestScene.cs | 95 +++++++++++++++++-- .../Visual/OnlinePlay/TestRoomContainer.cs | 2 +- 8 files changed, 129 insertions(+), 169 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/RoomManagerTestScene.cs delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/RoomManagerTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/RoomManagerTestScene.cs deleted file mode 100644 index c665a57452..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/RoomManagerTestScene.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Game.Beatmaps; -using osu.Game.Online.Rooms; -using osu.Game.Rulesets; -using osu.Game.Screens.OnlinePlay; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public abstract class RoomManagerTestScene : RoomTestScene - { - [Cached(Type = typeof(IRoomManager))] - protected TestRoomManager RoomManager { get; } = new TestRoomManager(); - - public override void SetUpSteps() - { - base.SetUpSteps(); - - AddStep("clear rooms", () => RoomManager.Rooms.Clear()); - } - - protected void AddRooms(int count, RulesetInfo ruleset = null) - { - AddStep("add rooms", () => - { - for (int i = 0; i < count; i++) - { - var room = new Room - { - RoomID = { Value = i }, - Name = { Value = $"Room {i}" }, - Host = { Value = new User { Username = "Host" } }, - EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, - Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal } - }; - - if (ruleset != null) - { - room.Playlist.Add(new PlaylistItem - { - Ruleset = { Value = ruleset }, - Beatmap = - { - Value = new BeatmapInfo - { - Metadata = new BeatmapMetadata() - } - } - }); - } - - RoomManager.Rooms.Add(room); - } - }); - } - } -} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestRoomManager.cs deleted file mode 100644 index 1785c99784..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestRoomManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Bindables; -using osu.Game.Online.Rooms; -using osu.Game.Screens.OnlinePlay; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestRoomManager : IRoomManager - { - public event Action RoomsUpdated - { - add { } - remove { } - } - - public readonly BindableList Rooms = new BindableList(); - - public IBindable InitialRoomsReceived { get; } = new Bindable(true); - - IBindableList IRoomManager.Rooms => Rooms; - - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) => Rooms.Add(room); - - public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) - { - } - - public void PartRoom() - { - } - } -} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 5682fd5c3c..d63d52a463 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -10,12 +10,13 @@ using osu.Game.Online.Rooms; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneLoungeRoomsContainer : RoomManagerTestScene + public class TestSceneLoungeRoomsContainer : OnlinePlaySubScreenTestScene { private RoomsContainer container; @@ -34,7 +35,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestBasicListChanges() { - AddRooms(3); + AddStep("add rooms", () => RoomManager.AddRooms(3)); AddAssert("has 3 rooms", () => container.Rooms.Count == 3); AddStep("remove first room", () => RoomManager.Rooms.Remove(RoomManager.Rooms.FirstOrDefault())); @@ -51,7 +52,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestKeyboardNavigation() { - AddRooms(3); + AddStep("add rooms", () => RoomManager.AddRooms(3)); AddAssert("no selection", () => checkRoomSelected(null)); @@ -72,7 +73,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestClickDeselection() { - AddRooms(1); + AddStep("add room", () => RoomManager.AddRooms(1)); AddAssert("no selection", () => checkRoomSelected(null)); @@ -91,7 +92,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestStringFiltering() { - AddRooms(4); + AddStep("add rooms", () => RoomManager.AddRooms(4)); AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4); @@ -107,8 +108,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestRulesetFiltering() { - AddRooms(2, new OsuRuleset().RulesetInfo); - AddRooms(3, new CatchRuleset().RulesetInfo); + AddStep("add rooms", () => RoomManager.AddRooms(2, new OsuRuleset().RulesetInfo)); + AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo)); AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5); @@ -121,7 +122,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3); } - private bool checkRoomSelected(Room room) => Room == room; + private bool checkRoomSelected(Room room) => SelectedRoom.Value == room; private void joinRequested(Room room) => room.Status.Value = new JoinedRoomStatus(); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index b958afd183..4f10877f95 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -14,6 +14,7 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -86,6 +87,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("reset", () => { + SelectedRoom.Value = new Room(); Ruleset.Value = new OsuRuleset().RulesetInfo; Beatmap.SetDefault(); SelectedMods.Value = Array.Empty(); @@ -99,14 +101,14 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestItemAddedIfEmptyOnStart() { AddStep("finalise selection", () => songSelect.FinaliseSelection()); - AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1); } [Test] public void TestItemAddedWhenCreateNewItemClicked() { AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); - AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1); } [Test] @@ -114,7 +116,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); AddStep("finalise selection", () => songSelect.FinaliseSelection()); - AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1); } [Test] @@ -122,7 +124,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); - AddAssert("playlist has 2 items", () => Room.Playlist.Count == 2); + AddAssert("playlist has 2 items", () => SelectedRoom.Value.Playlist.Count == 2); } [Test] @@ -132,13 +134,13 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); AddStep("rearrange", () => { - var item = Room.Playlist[0]; - Room.Playlist.RemoveAt(0); - Room.Playlist.Add(item); + var item = SelectedRoom.Value.Playlist[0]; + SelectedRoom.Value.Playlist.RemoveAt(0); + SelectedRoom.Value.Playlist.Add(item); }); AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); - AddAssert("new item has id 2", () => Room.Playlist.Last().ID == 2); + AddAssert("new item has id 2", () => SelectedRoom.Value.Playlist.Last().ID == 2); } /// @@ -152,8 +154,8 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("change mod rate", () => ((OsuModDoubleTime)SelectedMods.Value[0]).SpeedChange.Value = 2); AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem()); - AddAssert("item 1 has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)Room.Playlist.First().RequiredMods[0]).SpeedChange.Value)); - AddAssert("item 2 has rate 2", () => Precision.AlmostEquals(2, ((OsuModDoubleTime)Room.Playlist.Last().RequiredMods[0]).SpeedChange.Value)); + AddAssert("item 1 has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0]).SpeedChange.Value)); + AddAssert("item 2 has rate 2", () => Precision.AlmostEquals(2, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.Last().RequiredMods[0]).SpeedChange.Value)); } /// @@ -175,7 +177,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem()); AddStep("change stored mod rate", () => mod.SpeedChange.Value = 2); - AddAssert("item has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)Room.Playlist.First().RequiredMods[0]).SpeedChange.Value)); + AddAssert("item has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0]).SpeedChange.Value)); } private class TestPlaylistsSongSelect : PlaylistsSongSelect diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 618447eae2..62a6f40d65 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -10,11 +10,11 @@ using osu.Game.Graphics.Containers; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Playlists; -using osu.Game.Tests.Visual.Multiplayer; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsLoungeSubScreen : RoomManagerTestScene + public class TestScenePlaylistsLoungeSubScreen : OnlinePlaySubScreenTestScene { private LoungeSubScreen loungeScreen; @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Playlists [Test] public void TestScrollSelectedIntoView() { - AddRooms(30); + AddStep("add rooms", () => RoomManager.AddRooms(30)); AddUntilStep("first room is not masked", () => checkRoomVisible(roomsContainer.Rooms.First())); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index 73f9fcd8fd..98efdd98ef 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -15,7 +15,6 @@ using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; -using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Playlists; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; @@ -27,9 +26,6 @@ namespace osu.Game.Tests.Visual.Playlists { public class TestScenePlaylistsRoomSubScreen : OnlinePlaySubScreenTestScene { - [Cached(typeof(IRoomManager))] - private readonly TestRoomManager roomManager = new TestRoomManager(); - private BeatmapManager manager; private RulesetStore rulesets; @@ -59,7 +55,8 @@ namespace osu.Game.Tests.Visual.Playlists [SetUpSteps] public void SetupSteps() { - AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(Room))); + AddStep("set room", () => SelectedRoom.Value = new Room()); + AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value))); AddUntilStep("wait for load", () => match.IsCurrentScreen()); } @@ -68,12 +65,12 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("set room properties", () => { - Room.RoomID.Value = 1; - Room.Name.Value = "my awesome room"; - Room.Host.Value = new User { Id = 2, Username = "peppy" }; - Room.RecentParticipants.Add(Room.Host.Value); - Room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); - Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.RoomID.Value = 1; + SelectedRoom.Value.Name.Value = "my awesome room"; + SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.RecentParticipants.Add(SelectedRoom.Value.Host.Value); + SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMinutes(5); + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo } @@ -89,9 +86,9 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("set room properties", () => { - Room.Name.Value = "my awesome room"; - Room.Host.Value = new User { Id = 2, Username = "peppy" }; - Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Name.Value = "my awesome room"; + SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo } @@ -105,7 +102,7 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddAssert("first playlist item selected", () => match.SelectedItem.Value == Room.Playlist[0]); + AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value.Playlist[0]); } [Test] @@ -123,9 +120,9 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("load room", () => { - Room.Name.Value = "my awesome room"; - Room.Host.Value = new User { Id = 2, Username = "peppy" }; - Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Name.Value = "my awesome room"; + SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = importedSet.Beatmaps[0] }, Ruleset = { Value = new OsuRuleset().RulesetInfo } @@ -156,30 +153,5 @@ namespace osu.Game.Tests.Visual.Playlists { } } - - private class TestRoomManager : IRoomManager - { - public event Action RoomsUpdated - { - add => throw new NotImplementedException(); - remove => throw new NotImplementedException(); - } - - public IBindable InitialRoomsReceived { get; } = new Bindable(true); - - public IBindableList Rooms { get; } = new BindableList(); - - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - { - room.RoomID.Value = 1; - onSuccess?.Invoke(room); - } - - public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) => onSuccess?.Invoke(room); - - public void PartRoom() - { - } - } } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs index 27cb6496ce..177f6635a7 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs @@ -2,20 +2,37 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Game.Beatmaps; using osu.Game.Online.Rooms; +using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.OnlinePlay; +using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Users; namespace osu.Game.Tests.Visual.OnlinePlay { + /// + /// A providing all the dependencies cached by for testing s. + /// public abstract class OnlinePlaySubScreenTestScene : ScreenTestScene { /// - /// The cached . + /// The cached . /// - protected Room Room { get; private set; } + protected Bindable SelectedRoom { get; private set; } + + /// + /// The cached + /// + protected TestRoomManager RoomManager { get; private set; } + + protected Bindable Filter { get; private set; } + + protected OngoingOperationTracker OngoingOperationTracker { get; private set; } public override void SetUpSteps() { @@ -35,16 +52,80 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// The resultant dependency container. protected virtual IReadOnlyDependencyContainer CreateScreenDependencies(IReadOnlyDependencyContainer parent) { - Room = new Room(); + SelectedRoom = new Bindable(); + RoomManager = new TestRoomManager(); + Filter = new Bindable(new FilterCriteria()); + OngoingOperationTracker = new OngoingOperationTracker(); - var dependencies = new DependencyContainer( - new CachedModelDependencyContainer(parent) { Model = { Value = Room } }); - - dependencies.Cache(new Bindable(Room)); + var dependencies = new DependencyContainer(new CachedModelDependencyContainer(parent) { Model = { BindTarget = SelectedRoom } }); + dependencies.CacheAs(SelectedRoom); + dependencies.CacheAs(RoomManager); + dependencies.CacheAs(Filter); + dependencies.CacheAs(OngoingOperationTracker); return dependencies; } + protected class TestRoomManager : IRoomManager + { + public event Action RoomsUpdated + { + add { } + remove { } + } + + public readonly BindableList Rooms = new BindableList(); + + public IBindable InitialRoomsReceived { get; } = new Bindable(true); + + IBindableList IRoomManager.Rooms => Rooms; + + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) + { + room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; + Rooms.Add(room); + onSuccess?.Invoke(room); + } + + public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) => onSuccess?.Invoke(room); + + public void PartRoom() + { + } + + public void AddRooms(int count, RulesetInfo ruleset = null) + { + for (int i = 0; i < count; i++) + { + var room = new Room + { + RoomID = { Value = i }, + Name = { Value = $"Room {i}" }, + Host = { Value = new User { Username = "Host" } }, + EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, + Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal } + }; + + if (ruleset != null) + { + room.Playlist.Add(new PlaylistItem + { + Ruleset = { Value = ruleset }, + Beatmap = + { + Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata() + } + } + }); + } + + CreateRoom(room); + } + } + } + /// /// A dummy screen used for injecting new dependencies into the hierarchy before any screen is pushed via . /// diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs index c2abcdfd08..7ff2e5133e 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs @@ -10,7 +10,7 @@ using osu.Game.Online.Rooms; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// Contains a that is resolvable by components in test scenes. + /// Contains a single that is resolvable by components in test scenes. /// public class TestRoomContainer : Container { From a21cf87b5fcee946600bbf22100397094383fbfe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 19:13:50 +0900 Subject: [PATCH 028/119] Split room manager and allow overrides --- .../TestSceneLoungeRoomsContainer.cs | 5 ++ .../TestScenePlaylistsLoungeSubScreen.cs | 9 +-- .../OnlinePlaySubScreenTestScene.cs | 70 +----------------- .../Visual/OnlinePlay/TestBasicRoomManager.cs | 74 +++++++++++++++++++ 4 files changed, 87 insertions(+), 71 deletions(-) create mode 100644 osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index d63d52a463..22e7acce44 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; +using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Graphics; @@ -18,6 +19,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneLoungeRoomsContainer : OnlinePlaySubScreenTestScene { + protected new TestBasicRoomManager RoomManager => (TestBasicRoomManager)base.RoomManager; + private RoomsContainer container; [BackgroundDependencyLoader] @@ -32,6 +35,8 @@ namespace osu.Game.Tests.Visual.Multiplayer }; } + protected override IRoomManager CreateRoomManager() => new TestBasicRoomManager(); + [Test] public void TestBasicListChanges() { diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 62a6f40d65..34e66b9cb2 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -3,10 +3,10 @@ using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Graphics.Containers; +using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Playlists; @@ -16,12 +16,11 @@ namespace osu.Game.Tests.Visual.Playlists { public class TestScenePlaylistsLoungeSubScreen : OnlinePlaySubScreenTestScene { + protected new TestBasicRoomManager RoomManager => (TestBasicRoomManager)base.RoomManager; + private LoungeSubScreen loungeScreen; - [BackgroundDependencyLoader] - private void load() - { - } + protected override IRoomManager CreateRoomManager() => new TestBasicRoomManager(); public override void SetUpSteps() { diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs index 177f6635a7..c4a8658d93 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs @@ -2,16 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Game.Beatmaps; using osu.Game.Online.Rooms; -using osu.Game.Rulesets; using osu.Game.Screens; using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge.Components; -using osu.Game.Users; namespace osu.Game.Tests.Visual.OnlinePlay { @@ -28,7 +24,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The cached /// - protected TestRoomManager RoomManager { get; private set; } + protected IRoomManager RoomManager { get; private set; } protected Bindable Filter { get; private set; } @@ -53,78 +49,20 @@ namespace osu.Game.Tests.Visual.OnlinePlay protected virtual IReadOnlyDependencyContainer CreateScreenDependencies(IReadOnlyDependencyContainer parent) { SelectedRoom = new Bindable(); - RoomManager = new TestRoomManager(); + RoomManager = CreateRoomManager(); Filter = new Bindable(new FilterCriteria()); OngoingOperationTracker = new OngoingOperationTracker(); var dependencies = new DependencyContainer(new CachedModelDependencyContainer(parent) { Model = { BindTarget = SelectedRoom } }); dependencies.CacheAs(SelectedRoom); - dependencies.CacheAs(RoomManager); + dependencies.CacheAs(RoomManager); dependencies.CacheAs(Filter); dependencies.CacheAs(OngoingOperationTracker); return dependencies; } - protected class TestRoomManager : IRoomManager - { - public event Action RoomsUpdated - { - add { } - remove { } - } - - public readonly BindableList Rooms = new BindableList(); - - public IBindable InitialRoomsReceived { get; } = new Bindable(true); - - IBindableList IRoomManager.Rooms => Rooms; - - public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) - { - room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; - Rooms.Add(room); - onSuccess?.Invoke(room); - } - - public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) => onSuccess?.Invoke(room); - - public void PartRoom() - { - } - - public void AddRooms(int count, RulesetInfo ruleset = null) - { - for (int i = 0; i < count; i++) - { - var room = new Room - { - RoomID = { Value = i }, - Name = { Value = $"Room {i}" }, - Host = { Value = new User { Username = "Host" } }, - EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, - Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal } - }; - - if (ruleset != null) - { - room.Playlist.Add(new PlaylistItem - { - Ruleset = { Value = ruleset }, - Beatmap = - { - Value = new BeatmapInfo - { - Metadata = new BeatmapMetadata() - } - } - }); - } - - CreateRoom(room); - } - } - } + protected virtual IRoomManager CreateRoomManager() => new TestBasicRoomManager(); /// /// A dummy screen used for injecting new dependencies into the hierarchy before any screen is pushed via . diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs new file mode 100644 index 0000000000..fd81072651 --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Online.Rooms; +using osu.Game.Rulesets; +using osu.Game.Screens.OnlinePlay; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + public class TestBasicRoomManager : IRoomManager + { + public event Action RoomsUpdated + { + add { } + remove { } + } + + public readonly BindableList Rooms = new BindableList(); + + public IBindable InitialRoomsReceived { get; } = new Bindable(true); + + IBindableList IRoomManager.Rooms => Rooms; + + public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) + { + room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1; + Rooms.Add(room); + onSuccess?.Invoke(room); + } + + public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) => onSuccess?.Invoke(room); + + public void PartRoom() + { + } + + public void AddRooms(int count, RulesetInfo ruleset = null) + { + for (int i = 0; i < count; i++) + { + var room = new Room + { + RoomID = { Value = i }, + Name = { Value = $"Room {i}" }, + Host = { Value = new User { Username = "Host" } }, + EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) }, + Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal } + }; + + if (ruleset != null) + { + room.Playlist.Add(new PlaylistItem + { + Ruleset = { Value = ruleset }, + Beatmap = + { + Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata() + } + } + }); + } + + CreateRoom(room); + } + } + } +} From 9cf2c9ddaef526ec9cc3ed8f3b08e8247e1b1765 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 21:02:21 +0900 Subject: [PATCH 029/119] Fix incorrect dependency creation --- osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs index 7ff2e5133e..d75281e772 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer( - new CachedModelDependencyContainer(parent) { Model = { Value = Room } }); + new CachedModelDependencyContainer(base.CreateChildDependencies(parent)) { Model = { Value = Room } }); dependencies.Cache(new Bindable(Room)); From 5820793d1119f82bfeb772a835cfdd220277a356 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 20:44:48 +0900 Subject: [PATCH 030/119] Make TestMultiplayerRoomContainer inherit TestRoomContainer --- .../Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs index 1abf4d8f5d..d44b55c3c1 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs @@ -8,10 +8,11 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge.Components; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestMultiplayerRoomContainer : Container + public class TestMultiplayerRoomContainer : TestRoomContainer { protected override Container Content => content; private readonly Container content; From 8fba7d2423774f35c5e1182c4dcfe22992f9dad9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 Jun 2021 21:02:04 +0900 Subject: [PATCH 031/119] Remove MultiplayerTestScene inheritance from simple test scenes --- .../TestSceneFreeModSelectOverlay.cs | 11 +- .../TestSceneMultiSpectatorLeaderboard.cs | 112 +++++++++--------- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index 26a0301d8a..25de2d0df3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -7,14 +7,17 @@ using osu.Game.Screens.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneFreeModSelectOverlay : MultiplayerTestScene + public class TestSceneFreeModSelectOverlay : OsuTestScene { [SetUp] - public new void Setup() => Schedule(() => + public void Setup() => Schedule(() => { - Child = new FreeModSelectOverlay + Child = new TestMultiplayerRoomContainer { - State = { Value = Visibility.Visible } + Child = new FreeModSelectOverlay + { + State = { Value = Visibility.Visible } + } }; }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 5ad35be0ec..9ec85d360f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -1,15 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Framework.Threading; using osu.Framework.Timing; using osu.Game.Database; using osu.Game.Online.Spectator; @@ -21,61 +24,38 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene + public class TestSceneMultiSpectatorLeaderboard : OsuTestScene { - [Cached(typeof(SpectatorClient))] - private TestSpectatorClient spectatorClient = new TestSpectatorClient(); + private Dictionary clocks; - [Cached(typeof(UserLookupCache))] - private UserLookupCache lookupCache = new TestUserLookupCache(); - - protected override Container Content => content; - private readonly Container content; - - private readonly Dictionary clocks = new Dictionary - { - { PLAYER_1_ID, new ManualClock() }, - { PLAYER_2_ID, new ManualClock() } - }; - - public TestSceneMultiSpectatorLeaderboard() - { - base.Content.AddRange(new Drawable[] - { - spectatorClient, - lookupCache, - content = new Container { RelativeSizeAxes = Axes.Both } - }); - } + private MultiSpectatorLeaderboard leaderboard; + private TestContainer container; [SetUpSteps] - public new void SetUpSteps() + public void SetUpSteps() { - MultiSpectatorLeaderboard leaderboard = null; - AddStep("reset", () => { - Clear(); - - foreach (var (userId, clock) in clocks) + clocks = new Dictionary { - spectatorClient.EndPlay(userId); - clock.CurrentTime = 0; - } + { MultiplayerTestScene.PLAYER_1_ID, new ManualClock() }, + { MultiplayerTestScene.PLAYER_2_ID, new ManualClock() } + }; + + Child = container = new TestContainer(); + + foreach (var (userId, _) in clocks) + container.SpectatorClient.StartPlay(userId, 0); }); AddStep("create leaderboard", () => { - foreach (var (userId, _) in clocks) - spectatorClient.StartPlay(userId, 0); - Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); - var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); var scoreProcessor = new OsuScoreProcessor(); scoreProcessor.ApplyBeatmap(playable); - LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, clocks.Keys.ToArray()) { Expanded = { Value = true } }, Add); + container.LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, clocks.Keys.ToArray()) { Expanded = { Value = true } }, container.Add); }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); @@ -96,42 +76,42 @@ namespace osu.Game.Tests.Visual.Multiplayer // For player 2, send frames in sets of 10. for (int i = 0; i < 100; i++) { - spectatorClient.SendFrames(PLAYER_1_ID, i, 1); + container.SpectatorClient.SendFrames(MultiplayerTestScene.PLAYER_1_ID, i, 1); if (i % 10 == 0) - spectatorClient.SendFrames(PLAYER_2_ID, i, 10); + container.SpectatorClient.SendFrames(MultiplayerTestScene.PLAYER_2_ID, i, 10); } }); - assertCombo(PLAYER_1_ID, 1); - assertCombo(PLAYER_2_ID, 10); + assertCombo(MultiplayerTestScene.PLAYER_1_ID, 1); + assertCombo(MultiplayerTestScene.PLAYER_2_ID, 10); // Advance to a point where only user player 1's frame changes. setTime(500); - assertCombo(PLAYER_1_ID, 5); - assertCombo(PLAYER_2_ID, 10); + assertCombo(MultiplayerTestScene.PLAYER_1_ID, 5); + assertCombo(MultiplayerTestScene.PLAYER_2_ID, 10); // Advance to a point where both user's frame changes. setTime(1100); - assertCombo(PLAYER_1_ID, 11); - assertCombo(PLAYER_2_ID, 20); + assertCombo(MultiplayerTestScene.PLAYER_1_ID, 11); + assertCombo(MultiplayerTestScene.PLAYER_2_ID, 20); // Advance user player 2 only to a point where its frame changes. - setTime(PLAYER_2_ID, 2100); - assertCombo(PLAYER_1_ID, 11); - assertCombo(PLAYER_2_ID, 30); + setTime(MultiplayerTestScene.PLAYER_2_ID, 2100); + assertCombo(MultiplayerTestScene.PLAYER_1_ID, 11); + assertCombo(MultiplayerTestScene.PLAYER_2_ID, 30); // Advance both users beyond their last frame setTime(101 * 100); - assertCombo(PLAYER_1_ID, 100); - assertCombo(PLAYER_2_ID, 100); + assertCombo(MultiplayerTestScene.PLAYER_1_ID, 100); + assertCombo(MultiplayerTestScene.PLAYER_2_ID, 100); } [Test] public void TestNoFrames() { - assertCombo(PLAYER_1_ID, 0); - assertCombo(PLAYER_2_ID, 0); + assertCombo(MultiplayerTestScene.PLAYER_1_ID, 0); + assertCombo(MultiplayerTestScene.PLAYER_2_ID, 0); } private void setTime(double time) => AddStep($"set time {time}", () => @@ -146,6 +126,32 @@ namespace osu.Game.Tests.Visual.Multiplayer private void assertCombo(int userId, int expectedCombo) => AddUntilStep($"player {userId} has {expectedCombo} combo", () => this.ChildrenOfType().Single(s => s.User?.Id == userId).Combo.Value == expectedCombo); + private class TestContainer : TestMultiplayerRoomContainer + { + [Cached(typeof(SpectatorClient))] + public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); + + [Cached(typeof(UserLookupCache))] + public readonly UserLookupCache LookupCache = new TestUserLookupCache(); + + protected override Container Content => content; + private readonly Container content; + + public TestContainer() + { + AddRangeInternal(new Drawable[] + { + SpectatorClient, + LookupCache, + content = new Container { RelativeSizeAxes = Axes.Both } + }); + } + + public new Task LoadComponentAsync([NotNull] TLoadable component, Action onLoaded = null, CancellationToken cancellation = default, Scheduler scheduler = null) + where TLoadable : Drawable + => base.LoadComponentAsync(component, onLoaded, cancellation, scheduler); + } + private class TestUserLookupCache : UserLookupCache { protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) From aa5d22d04a4ecf0c0bc315ae7ce3ad1fd7b50b32 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 13:02:19 +0900 Subject: [PATCH 032/119] Remove "test container", make everything go through OnlinePlayTestScene --- .../Multiplayer/TestSceneLoungeRoomInfo.cs | 32 +++--- .../TestSceneLoungeRoomsContainer.cs | 7 +- .../TestSceneMatchBeatmapDetailArea.cs | 25 ++--- .../Multiplayer/TestSceneMatchHeader.cs | 19 ++-- .../Multiplayer/TestSceneMatchLeaderboard.cs | 20 ++-- .../TestSceneMultiplayerMatchFooter.cs | 16 +-- .../TestScenePlaylistsSongSelect.cs | 2 +- .../TestScenePlaylistsLoungeSubScreen.cs | 7 +- .../TestScenePlaylistsMatchSettingsOverlay.cs | 49 +++++---- .../TestScenePlaylistsParticipantsList.cs | 18 ++-- .../TestScenePlaylistsRoomSubScreen.cs | 2 +- .../IMultiplayerRoomTestDependencies.cs | 22 ++++ .../MultiplayerRoomTestDependencies.cs | 23 ++++ .../MultiplayerSubScreenTestScene.cs | 17 +++ .../TestMultiplayerRoomContainer.cs | 3 +- ...RoomManager.cs => BasicTestRoomManager.cs} | 2 +- .../OnlinePlay/IRoomTestDependencies.cs | 38 +++++++ .../OnlinePlaySubScreenTestScene.cs | 83 --------------- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 100 ++++++++++++++++++ .../Visual/OnlinePlay/RoomTestDependencies.cs | 78 ++++++++++++++ .../Visual/OnlinePlay/TestRoomContainer.cs | 37 ------- 21 files changed, 370 insertions(+), 230 deletions(-) create mode 100644 osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs create mode 100644 osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs create mode 100644 osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs rename osu.Game/Tests/Visual/OnlinePlay/{TestBasicRoomManager.cs => BasicTestRoomManager.cs} (97%) create mode 100644 osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs delete mode 100644 osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs create mode 100644 osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs create mode 100644 osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs delete mode 100644 osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs index 73f7865208..471d0b6c98 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs @@ -4,6 +4,7 @@ using System; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; @@ -11,28 +12,25 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneLoungeRoomInfo : OsuTestScene + public class TestSceneLoungeRoomInfo : OnlinePlayTestScene { - private TestRoomContainer roomContainer; - [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = roomContainer = new TestRoomContainer + SelectedRoom.Value = new Room(); + + Child = new RoomInfo { - Child = new RoomInfo - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 500 - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500 }; }); [Test] public void TestNonSelectedRoom() { - AddStep("set null room", () => roomContainer.Room.RoomID.Value = null); + AddStep("set null room", () => SelectedRoom.Value.RoomID.Value = null); } [Test] @@ -40,11 +38,11 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("set open room", () => { - roomContainer.Room.RoomID.Value = 0; - roomContainer.Room.Name.Value = "Room 0"; - roomContainer.Room.Host.Value = new User { Username = "peppy", Id = 2 }; - roomContainer.Room.EndDate.Value = DateTimeOffset.Now.AddMonths(1); - roomContainer.Room.Status.Value = new RoomStatusOpen(); + SelectedRoom.Value.RoomID.Value = 0; + SelectedRoom.Value.Name.Value = "Room 0"; + SelectedRoom.Value.Host.Value = new User { Username = "peppy", Id = 2 }; + SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMonths(1); + SelectedRoom.Value.Status.Value = new RoomStatusOpen(); }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 22e7acce44..a78cff0650 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -9,7 +9,6 @@ using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; -using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Visual.OnlinePlay; using osuTK.Graphics; @@ -17,9 +16,9 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneLoungeRoomsContainer : OnlinePlaySubScreenTestScene + public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene { - protected new TestBasicRoomManager RoomManager => (TestBasicRoomManager)base.RoomManager; + protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager; private RoomsContainer container; @@ -35,8 +34,6 @@ namespace osu.Game.Tests.Visual.Multiplayer }; } - protected override IRoomManager CreateRoomManager() => new TestBasicRoomManager(); - [Test] public void TestBasicListChanges() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index d114ae8abf..d66603a448 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -16,7 +16,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchBeatmapDetailArea : OsuTestScene + public class TestSceneMatchBeatmapDetailArea : OnlinePlayTestScene { [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -24,28 +24,25 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private RulesetStore rulesetStore { get; set; } - private TestRoomContainer roomContainer; - [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = roomContainer = new TestRoomContainer + SelectedRoom.Value = new Room(); + + Child = new MatchBeatmapDetailArea { - Child = new MatchBeatmapDetailArea - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500), - CreateNewItem = createNewItem - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500), + CreateNewItem = createNewItem }; }); private void createNewItem() { - roomContainer.Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Playlist.Add(new PlaylistItem { - ID = roomContainer.Room.Playlist.Count, + ID = SelectedRoom.Value.Playlist.Count, Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo }, RequiredMods = diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index 25cdfd4a90..3557bd9127 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -12,17 +12,14 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchHeader : OsuTestScene + public class TestSceneMatchHeader : OnlinePlayTestScene { - private TestRoomContainer roomContainer; - [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = roomContainer = new TestRoomContainer - { - Child = new Header() - }; + SelectedRoom.Value = new Room(); + + Child = new Header(); }); [Test] @@ -30,7 +27,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("set basic room", () => { - roomContainer.Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { @@ -54,8 +51,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - roomContainer.Room.Name.Value = "A very awesome room"; - roomContainer.Room.Host.Value = new User { Id = 2, Username = "peppy" }; + SelectedRoom.Value.Name.Value = "A very awesome room"; + SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 467df97cb9..a7a5f3af39 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -15,7 +15,7 @@ using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchLeaderboard : OsuTestScene + public class TestSceneMatchLeaderboard : OnlinePlayTestScene { [BackgroundDependencyLoader] private void load() @@ -59,18 +59,16 @@ namespace osu.Game.Tests.Visual.Multiplayer } [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = new TestRoomContainer + SelectedRoom.Value = new Room { RoomID = { Value = 3 } }; + + Child = new MatchLeaderboard { - Room = { RoomID = { Value = 3 } }, - Child = new MatchLeaderboard - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(550f, 450f), - Scope = MatchLeaderboardScope.Overall, - } + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(550f, 450f), + Scope = MatchLeaderboardScope.Overall, }; }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index 6b03b53b4b..afe66d2686 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -1,27 +1,27 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchFooter : MultiplayerTestScene + public class TestSceneMultiplayerMatchFooter : OnlinePlayTestScene { - [Cached] - private readonly OnlinePlayBeatmapAvailabilityTracker availablilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); - - [BackgroundDependencyLoader] - private void load() + [SetUp] + public new void Setup() => Schedule(() => { + SelectedRoom.Value = new Room(); + Child = new MultiplayerMatchFooter { Anchor = Anchor.Centre, Origin = Anchor.Centre, Height = 50 }; - } + }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index 4f10877f95..e4bf9b36ed 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -25,7 +25,7 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestScenePlaylistsSongSelect : OnlinePlaySubScreenTestScene + public class TestScenePlaylistsSongSelect : OnlinePlayTestScene { [Resolved] private BeatmapManager beatmapManager { get; set; } diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 34e66b9cb2..b16b61c5c7 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -6,7 +6,6 @@ using NUnit.Framework; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Graphics.Containers; -using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Playlists; @@ -14,14 +13,12 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsLoungeSubScreen : OnlinePlaySubScreenTestScene + public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene { - protected new TestBasicRoomManager RoomManager => (TestBasicRoomManager)base.RoomManager; + protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager; private LoungeSubScreen loungeScreen; - protected override IRoomManager CreateRoomManager() => new TestBasicRoomManager(); - public override void SetUpSteps() { base.SetUpSteps(); diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 94aed2ecfa..b52b6a6a0e 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -3,7 +3,6 @@ using System; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,24 +15,23 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsMatchSettingsOverlay : OsuTestScene + public class TestScenePlaylistsMatchSettingsOverlay : OnlinePlayTestScene { - [Cached(Type = typeof(IRoomManager))] - private TestRoomManager roomManager = new TestRoomManager(); + protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager; - private TestRoomContainer roomContainer; private TestRoomSettings settings; + protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = roomContainer = new TestRoomContainer + SelectedRoom.Value = new Room(); + + Child = settings = new TestRoomSettings { - Child = settings = new TestRoomSettings - { - RelativeSizeAxes = Axes.Both, - State = { Value = Visibility.Visible } - } + RelativeSizeAxes = Axes.Both, + State = { Value = Visibility.Visible } }; }); @@ -42,19 +40,19 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("clear name and beatmap", () => { - roomContainer.Room.Name.Value = ""; - roomContainer.Room.Playlist.Clear(); + SelectedRoom.Value.Name.Value = ""; + SelectedRoom.Value.Playlist.Clear(); }); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set name", () => roomContainer.Room.Name.Value = "Room name"); + AddStep("set name", () => SelectedRoom.Value.Name.Value = "Room name"); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set beatmap", () => roomContainer.Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } })); + AddStep("set beatmap", () => SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } })); AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value); - AddStep("clear name", () => roomContainer.Room.Name.Value = ""); + AddStep("clear name", () => SelectedRoom.Value.Name.Value = ""); AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); } @@ -70,9 +68,9 @@ namespace osu.Game.Tests.Visual.Playlists { settings.NameField.Current.Value = expected_name; settings.DurationField.Current.Value = expectedDuration; - roomContainer.Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); - roomManager.CreateRequested = r => + RoomManager.CreateRequested = r => { createdRoom = r; return true; @@ -91,11 +89,11 @@ namespace osu.Game.Tests.Visual.Playlists AddStep("setup", () => { - roomContainer.Room.Name.Value = "Test Room"; - roomContainer.Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); + SelectedRoom.Value.Name.Value = "Test Room"; + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }); fail = true; - roomManager.CreateRequested = _ => !fail; + RoomManager.CreateRequested = _ => !fail; }); AddAssert("error not displayed", () => !settings.ErrorText.IsPresent); @@ -122,7 +120,12 @@ namespace osu.Game.Tests.Visual.Playlists public OsuSpriteText ErrorText => ((MatchSettings)Settings).ErrorText; } - private class TestRoomManager : IRoomManager + private class TestDependencies : RoomTestDependencies + { + protected override IRoomManager CreateRoomManager() => new TestRoomManager(); + } + + protected class TestRoomManager : IRoomManager { public const string FAILED_TEXT = "failed"; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs index 02ddfe4e79..76a78c0a3c 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs @@ -3,27 +3,23 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Users; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsParticipantsList : OsuTestScene + public class TestScenePlaylistsParticipantsList : OnlinePlayTestScene { - private TestRoomContainer roomContainer; - [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = roomContainer = new TestRoomContainer - { - Room = { RoomID = { Value = 7 } } - }; + SelectedRoom.Value = new Room { RoomID = { Value = 7 } }; for (int i = 0; i < 50; i++) { - roomContainer.Room.RecentParticipants.Add(new User + SelectedRoom.Value.RecentParticipants.Add(new User { Username = "peppy", Statistics = new UserStatistics { GlobalRank = 1234 }, @@ -37,7 +33,7 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("create component", () => { - roomContainer.Child = new ParticipantsDisplay(Direction.Horizontal) + Child = new ParticipantsDisplay(Direction.Horizontal) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -51,7 +47,7 @@ namespace osu.Game.Tests.Visual.Playlists { AddStep("create component", () => { - roomContainer.Child = new ParticipantsDisplay(Direction.Vertical) + Child = new ParticipantsDisplay(Direction.Vertical) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs index 98efdd98ef..a0096c823f 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomSubScreen.cs @@ -24,7 +24,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Playlists { - public class TestScenePlaylistsRoomSubScreen : OnlinePlaySubScreenTestScene + public class TestScenePlaylistsRoomSubScreen : OnlinePlayTestScene { private BeatmapManager manager; private RulesetStore rulesets; diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs new file mode 100644 index 0000000000..0b53bdd04e --- /dev/null +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.OnlinePlay; +using osu.Game.Tests.Visual.OnlinePlay; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public interface IMultiplayerRoomTestDependencies : IRoomTestDependencies + { + /// + /// The cached . + /// + TestMultiplayerClient Client { get; } + + /// + /// The cached . + /// + new TestMultiplayerRoomManager RoomManager { get; } + } +} diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs new file mode 100644 index 0000000000..e3913dd291 --- /dev/null +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.OnlinePlay; +using osu.Game.Tests.Visual.OnlinePlay; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class MultiplayerRoomTestDependencies : RoomTestDependencies, IMultiplayerRoomTestDependencies + { + public TestMultiplayerClient Client { get; } + public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; + + public MultiplayerRoomTestDependencies() + { + Client = new TestMultiplayerClient(RoomManager); + CacheAs(Client); + } + + protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); + } +} diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs new file mode 100644 index 0000000000..5c405ee9d3 --- /dev/null +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Tests.Visual.OnlinePlay; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class MultiplayerSubScreenTestScene : OnlinePlayTestScene, IMultiplayerRoomTestDependencies + { + public TestMultiplayerClient Client => RoomDependencies.Client; + public new TestMultiplayerRoomManager RoomManager => RoomDependencies.RoomManager; + + protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; + + protected override RoomTestDependencies CreateRoomDependencies() => new MultiplayerRoomTestDependencies(); + } +} diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs index d44b55c3c1..1abf4d8f5d 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs @@ -8,11 +8,10 @@ using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Lounge.Components; -using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestMultiplayerRoomContainer : TestRoomContainer + public class TestMultiplayerRoomContainer : Container { protected override Container Content => content; private readonly Container content; diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs similarity index 97% rename from osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs rename to osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index fd81072651..67beea9117 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestBasicRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -12,7 +12,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.OnlinePlay { - public class TestBasicRoomManager : IRoomManager + public class BasicTestRoomManager : IRoomManager { public event Action RoomsUpdated { diff --git a/osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs new file mode 100644 index 0000000000..848e2aa77f --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay; +using osu.Game.Screens.OnlinePlay.Lounge.Components; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + public interface IRoomTestDependencies + { + /// + /// The cached . + /// + Bindable SelectedRoom { get; } + + /// + /// The cached + /// + IRoomManager RoomManager { get; } + + /// + /// The cached . + /// + Bindable Filter { get; } + + /// + /// The cached . + /// + OngoingOperationTracker OngoingOperationTracker { get; } + + /// + /// The cached . + /// + OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } + } +} diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs deleted file mode 100644 index c4a8658d93..0000000000 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlaySubScreenTestScene.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Online.Rooms; -using osu.Game.Screens; -using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; - -namespace osu.Game.Tests.Visual.OnlinePlay -{ - /// - /// A providing all the dependencies cached by for testing s. - /// - public abstract class OnlinePlaySubScreenTestScene : ScreenTestScene - { - /// - /// The cached . - /// - protected Bindable SelectedRoom { get; private set; } - - /// - /// The cached - /// - protected IRoomManager RoomManager { get; private set; } - - protected Bindable Filter { get; private set; } - - protected OngoingOperationTracker OngoingOperationTracker { get; private set; } - - public override void SetUpSteps() - { - base.SetUpSteps(); - - AddStep("create dependencies", () => LoadScreen(new DependenciesScreen(CreateScreenDependencies))); - } - - /// - /// Creates dependencies for any pushed via . - /// Invoked at the start of every test via . - /// - /// - /// This should be overridden to add any custom dependencies required by subclasses of . - /// - /// The parent dependency container. - /// The resultant dependency container. - protected virtual IReadOnlyDependencyContainer CreateScreenDependencies(IReadOnlyDependencyContainer parent) - { - SelectedRoom = new Bindable(); - RoomManager = CreateRoomManager(); - Filter = new Bindable(new FilterCriteria()); - OngoingOperationTracker = new OngoingOperationTracker(); - - var dependencies = new DependencyContainer(new CachedModelDependencyContainer(parent) { Model = { BindTarget = SelectedRoom } }); - dependencies.CacheAs(SelectedRoom); - dependencies.CacheAs(RoomManager); - dependencies.CacheAs(Filter); - dependencies.CacheAs(OngoingOperationTracker); - - return dependencies; - } - - protected virtual IRoomManager CreateRoomManager() => new TestBasicRoomManager(); - - /// - /// A dummy screen used for injecting new dependencies into the hierarchy before any screen is pushed via . - /// - private class DependenciesScreen : OsuScreen - { - private readonly Func createDependenciesFunc; - - public DependenciesScreen(Func createDependenciesFunc) - { - this.createDependenciesFunc = createDependenciesFunc; - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - => createDependenciesFunc(base.CreateChildDependencies(parent)); - } - } -} diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs new file mode 100644 index 0000000000..5e46ea0544 --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -0,0 +1,100 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay; +using osu.Game.Screens.OnlinePlay.Lounge.Components; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + /// + /// A providing all the dependencies cached by for testing s. + /// + public abstract class OnlinePlayTestScene : ScreenTestScene, IRoomTestDependencies + { + public Bindable SelectedRoom => RoomDependencies?.SelectedRoom; + public IRoomManager RoomManager => RoomDependencies?.RoomManager; + public Bindable Filter => RoomDependencies?.Filter; + public OngoingOperationTracker OngoingOperationTracker => RoomDependencies?.OngoingOperationTracker; + public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => RoomDependencies?.AvailabilityTracker; + + protected RoomTestDependencies RoomDependencies => delegatedDependencies?.RoomDependencies; + private DelegatedRoomDependencyContainer delegatedDependencies; + + protected override Container Content => content; + private readonly Container content; + private readonly Container drawableDependenciesContainer; + + protected OnlinePlayTestScene() + { + base.Content.AddRange(new Drawable[] + { + drawableDependenciesContainer = new Container { RelativeSizeAxes = Axes.Both }, + content = new Container { RelativeSizeAxes = Axes.Both }, + }); + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + delegatedDependencies = new DelegatedRoomDependencyContainer(base.CreateChildDependencies(parent)); + return delegatedDependencies; + } + + [SetUp] + public void Setup() => Schedule(() => + { + // Reset the room dependencies to a fresh state. + drawableDependenciesContainer.Clear(); + delegatedDependencies.RoomDependencies = CreateRoomDependencies(); + drawableDependenciesContainer.AddRange(RoomDependencies.DrawableComponents); + }); + + /// + /// Creates the room dependencies. Called every . + /// + /// + /// Any custom dependencies required for online-play sub-classes should be added here. + /// + protected virtual RoomTestDependencies CreateRoomDependencies() => new RoomTestDependencies(); + + /// + /// A providing a mutable lookup source for room dependencies. + /// + private class DelegatedRoomDependencyContainer : IReadOnlyDependencyContainer + { + /// + /// The room's dependencies. + /// + public RoomTestDependencies RoomDependencies { get; set; } + + private readonly IReadOnlyDependencyContainer parent; + private readonly DependencyContainer injectableDependencies; + + /// + /// Creates a new . + /// + /// The fallback to use when cannot satisfy a dependency. + public DelegatedRoomDependencyContainer(IReadOnlyDependencyContainer parent) + { + this.parent = parent; + injectableDependencies = new DependencyContainer(this); + } + + public object Get(Type type) + => RoomDependencies?.Get(type) ?? parent.Get(type); + + public object Get(Type type, CacheInfo info) + => RoomDependencies?.Get(type, info) ?? parent.Get(type, info); + + public void Inject(T instance) + where T : class + => injectableDependencies.Inject(instance); + } + } +} diff --git a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs new file mode 100644 index 0000000000..9d22f9e286 --- /dev/null +++ b/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs @@ -0,0 +1,78 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay; +using osu.Game.Screens.OnlinePlay.Lounge.Components; + +namespace osu.Game.Tests.Visual.OnlinePlay +{ + /// + /// Contains dependencies for testing online-play rooms. + /// + public class RoomTestDependencies : IReadOnlyDependencyContainer, IRoomTestDependencies + { + public Bindable SelectedRoom { get; } + public IRoomManager RoomManager { get; } + public Bindable Filter { get; } + public OngoingOperationTracker OngoingOperationTracker { get; } + public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; } + + /// + /// All cached dependencies which are also components. + /// + public IReadOnlyList DrawableComponents => drawableComponents; + + private readonly List drawableComponents = new List(); + private readonly DependencyContainer dependencies; + + public RoomTestDependencies() + { + SelectedRoom = new Bindable(); + RoomManager = CreateRoomManager(); + Filter = new Bindable(new FilterCriteria()); + OngoingOperationTracker = new OngoingOperationTracker(); + AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker(); + + dependencies = new DependencyContainer(new CachedModelDependencyContainer(null) { Model = { BindTarget = SelectedRoom } }); + + CacheAs(SelectedRoom); + CacheAs(RoomManager); + CacheAs(Filter); + CacheAs(OngoingOperationTracker); + CacheAs(AvailabilityTracker); + } + + public object Get(Type type) + => dependencies.Get(type); + + public object Get(Type type, CacheInfo info) + => dependencies.Get(type, info); + + public void Inject(T instance) + where T : class + => dependencies.Inject(instance); + + protected void Cache(object instance) + { + dependencies.Cache(instance); + if (instance is Drawable drawable) + drawableComponents.Add(drawable); + } + + protected void CacheAs(T instance) + where T : class + { + dependencies.CacheAs(instance); + if (instance is Drawable drawable) + drawableComponents.Add(drawable); + } + + protected virtual IRoomManager CreateRoomManager() => new BasicTestRoomManager(); + } +} diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs deleted file mode 100644 index d75281e772..0000000000 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomContainer.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Online.Rooms; - -namespace osu.Game.Tests.Visual.OnlinePlay -{ - /// - /// Contains a single that is resolvable by components in test scenes. - /// - public class TestRoomContainer : Container - { - /// - /// The cached . - /// - public readonly Room Room = new Room(); - - public TestRoomContainer() - { - RelativeSizeAxes = Axes.Both; - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer( - new CachedModelDependencyContainer(base.CreateChildDependencies(parent)) { Model = { Value = Room } }); - - dependencies.Cache(new Bindable(Room)); - - return dependencies; - } - } -} From 81a812e21690cc4231459765e9a4d8b859da3647 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 15:00:10 +0900 Subject: [PATCH 033/119] Rework MultiplayerTestScene to make use of OnlinePlayTestScene --- .../StatefulMultiplayerClientTest.cs | 8 +- .../TestSceneFreeModSelectOverlay.cs | 11 +- .../TestSceneLoungeRoomsContainer.cs | 11 +- .../TestSceneMultiSpectatorLeaderboard.cs | 85 +++++-------- .../TestSceneMultiSpectatorScreen.cs | 54 ++++---- .../TestSceneMultiplayerMatchSongSelect.cs | 2 +- .../TestSceneMultiplayerMatchSubScreen.cs | 10 +- .../TestSceneMultiplayerReadyButton.cs | 10 +- .../TestSceneMultiplayerRoomManager.cs | 120 +++++++----------- .../TestSceneMultiplayerSpectateButton.cs | 25 +--- .../MultiplayerSubScreenTestScene.cs | 17 --- .../Multiplayer/MultiplayerTestScene.cs | 55 +++----- .../TestMultiplayerRoomContainer.cs | 48 ------- .../Multiplayer/TestMultiplayerRoomManager.cs | 5 +- osu.Game/Tests/Visual/RoomTestScene.cs | 33 ----- 15 files changed, 159 insertions(+), 335 deletions(-) delete mode 100644 osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs delete mode 100644 osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs delete mode 100644 osu.Game/Tests/Visual/RoomTestScene.cs diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index adc1d6aede..0983b806e2 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Testing; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Rooms; using osu.Game.Tests.Visual.Multiplayer; using osu.Game.Users; @@ -50,7 +51,10 @@ namespace osu.Game.Tests.NonVisual.Multiplayer AddStep("create room initially in gameplay", () => { - Room.RoomID.Value = null; + var newRoom = new Room(); + newRoom.CopyFrom(SelectedRoom.Value); + + newRoom.RoomID.Value = null; Client.RoomSetupAction = room => { room.State = MultiplayerRoomState.Playing; @@ -61,7 +65,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer }); }; - RoomManager.CreateRoom(Room); + RoomManager.CreateRoom(newRoom); }); AddUntilStep("wait for room join", () => Client.Room != null); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index 25de2d0df3..26a0301d8a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -7,17 +7,14 @@ using osu.Game.Screens.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneFreeModSelectOverlay : OsuTestScene + public class TestSceneFreeModSelectOverlay : MultiplayerTestScene { [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Child = new TestMultiplayerRoomContainer + Child = new FreeModSelectOverlay { - Child = new FreeModSelectOverlay - { - State = { Value = Visibility.Visible } - } + State = { Value = Visibility.Visible } }; }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index a78cff0650..75cc687ee8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -3,7 +3,6 @@ using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Online.Rooms; @@ -22,8 +21,8 @@ namespace osu.Game.Tests.Visual.Multiplayer private RoomsContainer container; - [BackgroundDependencyLoader] - private void load() + [SetUp] + public new void Setup() => Schedule(() => { Child = container = new RoomsContainer { @@ -32,7 +31,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Width = 0.5f, JoinRequested = joinRequested }; - } + }); [Test] public void TestBasicListChanges() @@ -113,14 +112,14 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add rooms", () => RoomManager.AddRooms(2, new OsuRuleset().RulesetInfo)); AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo)); + // Todo: What even is this case...? + AddStep("set empty filter criteria", () => container.Filter(null)); AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5); AddStep("filter osu! rooms", () => container.Filter(new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo })); - AddUntilStep("2 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 2); AddStep("filter catch rooms", () => container.Filter(new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo })); - AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 9ec85d360f..54594fbfc8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -1,51 +1,48 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Testing; -using osu.Framework.Threading; using osu.Framework.Timing; using osu.Game.Database; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play.HUD; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiSpectatorLeaderboard : OsuTestScene + public class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene { - private Dictionary clocks; + public TestSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; + protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; + + private Dictionary clocks; private MultiSpectatorLeaderboard leaderboard; - private TestContainer container; [SetUpSteps] - public void SetUpSteps() + public new void SetUpSteps() { AddStep("reset", () => { + Clear(); + clocks = new Dictionary { - { MultiplayerTestScene.PLAYER_1_ID, new ManualClock() }, - { MultiplayerTestScene.PLAYER_2_ID, new ManualClock() } + { PLAYER_1_ID, new ManualClock() }, + { PLAYER_2_ID, new ManualClock() } }; - Child = container = new TestContainer(); - foreach (var (userId, _) in clocks) - container.SpectatorClient.StartPlay(userId, 0); + SpectatorClient.StartPlay(userId, 0); }); AddStep("create leaderboard", () => @@ -55,7 +52,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var scoreProcessor = new OsuScoreProcessor(); scoreProcessor.ApplyBeatmap(playable); - container.LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, clocks.Keys.ToArray()) { Expanded = { Value = true } }, container.Add); + LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, clocks.Keys.ToArray()) { Expanded = { Value = true } }, Add); }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); @@ -76,42 +73,42 @@ namespace osu.Game.Tests.Visual.Multiplayer // For player 2, send frames in sets of 10. for (int i = 0; i < 100; i++) { - container.SpectatorClient.SendFrames(MultiplayerTestScene.PLAYER_1_ID, i, 1); + SpectatorClient.SendFrames(PLAYER_1_ID, i, 1); if (i % 10 == 0) - container.SpectatorClient.SendFrames(MultiplayerTestScene.PLAYER_2_ID, i, 10); + SpectatorClient.SendFrames(PLAYER_2_ID, i, 10); } }); - assertCombo(MultiplayerTestScene.PLAYER_1_ID, 1); - assertCombo(MultiplayerTestScene.PLAYER_2_ID, 10); + assertCombo(PLAYER_1_ID, 1); + assertCombo(PLAYER_2_ID, 10); // Advance to a point where only user player 1's frame changes. setTime(500); - assertCombo(MultiplayerTestScene.PLAYER_1_ID, 5); - assertCombo(MultiplayerTestScene.PLAYER_2_ID, 10); + assertCombo(PLAYER_1_ID, 5); + assertCombo(PLAYER_2_ID, 10); // Advance to a point where both user's frame changes. setTime(1100); - assertCombo(MultiplayerTestScene.PLAYER_1_ID, 11); - assertCombo(MultiplayerTestScene.PLAYER_2_ID, 20); + assertCombo(PLAYER_1_ID, 11); + assertCombo(PLAYER_2_ID, 20); // Advance user player 2 only to a point where its frame changes. - setTime(MultiplayerTestScene.PLAYER_2_ID, 2100); - assertCombo(MultiplayerTestScene.PLAYER_1_ID, 11); - assertCombo(MultiplayerTestScene.PLAYER_2_ID, 30); + setTime(PLAYER_2_ID, 2100); + assertCombo(PLAYER_1_ID, 11); + assertCombo(PLAYER_2_ID, 30); // Advance both users beyond their last frame setTime(101 * 100); - assertCombo(MultiplayerTestScene.PLAYER_1_ID, 100); - assertCombo(MultiplayerTestScene.PLAYER_2_ID, 100); + assertCombo(PLAYER_1_ID, 100); + assertCombo(PLAYER_2_ID, 100); } [Test] public void TestNoFrames() { - assertCombo(MultiplayerTestScene.PLAYER_1_ID, 0); - assertCombo(MultiplayerTestScene.PLAYER_2_ID, 0); + assertCombo(PLAYER_1_ID, 0); + assertCombo(PLAYER_2_ID, 0); } private void setTime(double time) => AddStep($"set time {time}", () => @@ -126,30 +123,18 @@ namespace osu.Game.Tests.Visual.Multiplayer private void assertCombo(int userId, int expectedCombo) => AddUntilStep($"player {userId} has {expectedCombo} combo", () => this.ChildrenOfType().Single(s => s.User?.Id == userId).Combo.Value == expectedCombo); - private class TestContainer : TestMultiplayerRoomContainer - { - [Cached(typeof(SpectatorClient))] - public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); + protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); - [Cached(typeof(UserLookupCache))] + protected class TestDependencies : MultiplayerRoomTestDependencies + { + public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); public readonly UserLookupCache LookupCache = new TestUserLookupCache(); - protected override Container Content => content; - private readonly Container content; - - public TestContainer() + public TestDependencies() { - AddRangeInternal(new Drawable[] - { - SpectatorClient, - LookupCache, - content = new Container { RelativeSizeAxes = Axes.Both } - }); + CacheAs(SpectatorClient); + CacheAs(LookupCache); } - - public new Task LoadComponentAsync([NotNull] TLoadable component, Action onLoaded = null, CancellationToken cancellation = default, Scheduler scheduler = null) - where TLoadable : Drawable - => base.LoadComponentAsync(component, onLoaded, cancellation, scheduler); } private class TestUserLookupCache : UserLookupCache diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index b91391c409..64f4b4c0d6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -15,6 +15,7 @@ using osu.Game.Online.Spectator; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; using osu.Game.Users; @@ -22,11 +23,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiSpectatorScreen : MultiplayerTestScene { - [Cached(typeof(SpectatorClient))] - private TestSpectatorClient spectatorClient = new TestSpectatorClient(); + public TestSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; - [Cached(typeof(UserLookupCache))] - private UserLookupCache lookupCache = new TestUserLookupCache(); + protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; [Resolved] private OsuGameBase game { get; set; } @@ -51,25 +50,12 @@ namespace osu.Game.Tests.Visual.Multiplayer importedBeatmapId = importedBeatmap.OnlineBeatmapID ?? -1; } - public override void SetUpSteps() + [SetUp] + public new void Setup() => Schedule(() => { - base.SetUpSteps(); - - AddStep("reset sent frames", () => nextFrame.Clear()); - - AddStep("add streaming client", () => - { - Remove(spectatorClient); - Add(spectatorClient); - }); - - AddStep("finish previous gameplay", () => - { - foreach (var id in playingUserIds) - spectatorClient.EndPlay(id); - playingUserIds.Clear(); - }); - } + nextFrame.Clear(); + playingUserIds.Clear(); + }); [Test] public void TestDelayedStart() @@ -87,11 +73,11 @@ namespace osu.Game.Tests.Visual.Multiplayer loadSpectateScreen(false); AddWaitStep("wait a bit", 10); - AddStep("load player first_player_id", () => spectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId)); + AddStep("load player first_player_id", () => SpectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId)); AddUntilStep("one player added", () => spectatorScreen.ChildrenOfType().Count() == 1); AddWaitStep("wait a bit", 10); - AddStep("load player second_player_id", () => spectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId)); + AddStep("load player second_player_id", () => SpectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId)); AddUntilStep("two players added", () => spectatorScreen.ChildrenOfType().Count() == 2); } @@ -251,7 +237,7 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (int id in userIds) { Client.CurrentMatchPlayingUserIds.Add(id); - spectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); + SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUserIds.Add(id); nextFrame[id] = 0; } @@ -262,7 +248,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("end play", () => { - spectatorClient.EndPlay(userId); + SpectatorClient.EndPlay(userId); playingUserIds.Remove(userId); nextFrame.Remove(userId); }); @@ -276,7 +262,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { foreach (int id in userIds) { - spectatorClient.SendFrames(id, nextFrame[id], count); + SpectatorClient.SendFrames(id, nextFrame[id], count); nextFrame[id] += count; } }); @@ -298,6 +284,20 @@ namespace osu.Game.Tests.Visual.Multiplayer private PlayerArea getInstance(int userId) => spectatorScreen.ChildrenOfType().Single(p => p.UserId == userId); + protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + + protected class TestDependencies : MultiplayerRoomTestDependencies + { + public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); + public readonly UserLookupCache LookupCache = new TestUserLookupCache(); + + public TestDependencies() + { + CacheAs(SpectatorClient); + CacheAs(LookupCache); + } + } + internal class TestUserLookupCache : UserLookupCache { protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index 2725ef5976..8bcb9cebbc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -29,7 +29,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchSongSelect : ScreenTestScene + public class TestSceneMultiplayerMatchSongSelect : MultiplayerTestScene { private BeatmapManager manager; private RulesetStore rulesets; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index e8ebc0c426..955be6ca21 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -49,13 +49,13 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUp] public new void Setup() => Schedule(() => { - Room.Name.Value = "Test Room"; + SelectedRoom.Value = new Room { Name = { Value = "Test Room" } }; }); [SetUpSteps] public void SetupSteps() { - AddStep("load match", () => LoadScreen(screen = new MultiplayerMatchSubScreen(Room))); + AddStep("load match", () => LoadScreen(screen = new MultiplayerMatchSubScreen(SelectedRoom.Value))); AddUntilStep("wait for load", () => screen.IsCurrentScreen()); } @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("set playlist", () => { - Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo }, @@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("set playlist", () => { - Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo }, @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("set playlist", () => { - Room.Playlist.Add(new PlaylistItem + SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo }, Ruleset = { Value = new OsuRuleset().RulesetInfo }, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index 929cd6ca80..4f2ca34fb0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -27,7 +27,6 @@ namespace osu.Game.Tests.Visual.Multiplayer public class TestSceneMultiplayerReadyButton : MultiplayerTestScene { private MultiplayerReadyButton button; - private OnlinePlayBeatmapAvailabilityTracker beatmapTracker; private BeatmapSetInfo importedSet; private readonly Bindable selectedItem = new Bindable(); @@ -43,18 +42,13 @@ namespace osu.Game.Tests.Visual.Multiplayer Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default)); beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait(); - - Add(beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker - { - SelectedItem = { BindTarget = selectedItem } - }); - - Dependencies.Cache(beatmapTracker); } [SetUp] public new void Setup() => Schedule(() => { + AvailabilityTracker.SelectedItem.BindTo(selectedItem); + importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First(); Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()); selectedItem.Value = new PlaylistItem diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index 80e36916b1..302e6998cc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -3,37 +3,38 @@ using System; using NUnit.Framework; -using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { [HeadlessTest] - public class TestSceneMultiplayerRoomManager : OsuTestScene + public class TestSceneMultiplayerRoomManager : MultiplayerTestScene { - private TestMultiplayerRoomContainer roomContainer; - private TestMultiplayerRoomManager roomManager => roomContainer.RoomManager; + protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + + public TestSceneMultiplayerRoomManager() + : base(false) + { + } [Test] public void TestPollsInitially() { AddStep("create room manager with a few rooms", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - roomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); - roomManager.PartRoom(); - roomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); - roomManager.PartRoom(); - roomManager.ClearRooms(); - }); + RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1")); + RoomManager.PartRoom(); + RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2")); + RoomManager.PartRoom(); + RoomManager.ClearRooms(); }); - AddAssert("manager polled for rooms", () => ((RoomManager)roomManager).Rooms.Count == 2); - AddAssert("initial rooms received", () => roomManager.InitialRoomsReceived.Value); + AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); + AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); } [Test] @@ -41,19 +42,16 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room manager with a few rooms", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - roomManager.CreateRoom(createRoom()); - roomManager.PartRoom(); - roomManager.CreateRoom(createRoom()); - roomManager.PartRoom(); - }); + RoomManager.CreateRoom(createRoom()); + RoomManager.PartRoom(); + RoomManager.CreateRoom(createRoom()); + RoomManager.PartRoom(); }); - AddStep("disconnect", () => roomContainer.Client.Disconnect()); + AddStep("disconnect", () => Client.Disconnect()); - AddAssert("rooms cleared", () => ((RoomManager)roomManager).Rooms.Count == 0); - AddAssert("initial rooms not received", () => !roomManager.InitialRoomsReceived.Value); + AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0); + AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); } [Test] @@ -61,20 +59,17 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room manager with a few rooms", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - roomManager.CreateRoom(createRoom()); - roomManager.PartRoom(); - roomManager.CreateRoom(createRoom()); - roomManager.PartRoom(); - }); + RoomManager.CreateRoom(createRoom()); + RoomManager.PartRoom(); + RoomManager.CreateRoom(createRoom()); + RoomManager.PartRoom(); }); - AddStep("disconnect", () => roomContainer.Client.Disconnect()); - AddStep("connect", () => roomContainer.Client.Connect()); + AddStep("disconnect", () => Client.Disconnect()); + AddStep("connect", () => Client.Connect()); - AddAssert("manager polled for rooms", () => ((RoomManager)roomManager).Rooms.Count == 2); - AddAssert("initial rooms received", () => roomManager.InitialRoomsReceived.Value); + AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2); + AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value); } [Test] @@ -82,15 +77,12 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room manager with a room", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - roomManager.CreateRoom(createRoom()); - roomManager.ClearRooms(); - }); + RoomManager.CreateRoom(createRoom()); + RoomManager.ClearRooms(); }); - AddAssert("manager not polled for rooms", () => ((RoomManager)roomManager).Rooms.Count == 0); - AddAssert("initial rooms not received", () => !roomManager.InitialRoomsReceived.Value); + AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0); + AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value); } [Test] @@ -98,13 +90,10 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room manager with a room", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - roomManager.CreateRoom(createRoom()); - }); + RoomManager.CreateRoom(createRoom()); }); - AddUntilStep("multiplayer room joined", () => roomContainer.Client.Room != null); + AddUntilStep("multiplayer room joined", () => Client.Room != null); } [Test] @@ -112,14 +101,11 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room manager with a room", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - roomManager.CreateRoom(createRoom()); - roomManager.PartRoom(); - }); + RoomManager.CreateRoom(createRoom()); + RoomManager.PartRoom(); }); - AddAssert("multiplayer room parted", () => roomContainer.Client.Room == null); + AddAssert("multiplayer room parted", () => Client.Room == null); } [Test] @@ -127,16 +113,13 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("create room manager with a room", () => { - createRoomManager().With(d => d.OnLoadComplete += _ => - { - var r = createRoom(); - roomManager.CreateRoom(r); - roomManager.PartRoom(); - roomManager.JoinRoom(r); - }); + var r = createRoom(); + RoomManager.CreateRoom(r); + RoomManager.PartRoom(); + RoomManager.JoinRoom(r); }); - AddUntilStep("multiplayer room joined", () => roomContainer.Client.Room != null); + AddUntilStep("multiplayer room joined", () => Client.Room != null); } private Room createRoom(Action initFunc = null) @@ -161,18 +144,13 @@ namespace osu.Game.Tests.Visual.Multiplayer return room; } - private TestMultiplayerRoomManager createRoomManager() + private class TestDependencies : MultiplayerRoomTestDependencies { - Child = roomContainer = new TestMultiplayerRoomContainer + public TestDependencies() { - RoomManager = - { - TimeBetweenListingPolls = { Value = 1 }, - TimeBetweenSelectionPolls = { Value = 1 } - } - }; - - return roomManager; + RoomManager.TimeBetweenListingPolls.Value = 1; + RoomManager.TimeBetweenSelectionPolls.Value = 1; + } } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index d00404102c..070158f552 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -37,40 +37,19 @@ namespace osu.Game.Tests.Visual.Multiplayer private IDisposable readyClickOperation; - protected override Container Content => content; - private readonly Container content; - - public TestSceneMultiplayerSpectateButton() - { - base.Content.Add(content = new Container - { - RelativeSizeAxes = Axes.Both - }); - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - - return dependencies; - } - [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) { Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default)); - - var beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker { SelectedItem = { BindTarget = selectedItem } }; - base.Content.Add(beatmapTracker); - Dependencies.Cache(beatmapTracker); - beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait(); } [SetUp] public new void Setup() => Schedule(() => { + AvailabilityTracker.SelectedItem.BindTo(selectedItem); + importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First(); Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()); selectedItem.Value = new PlaylistItem diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs deleted file mode 100644 index 5c405ee9d3..0000000000 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerSubScreenTestScene.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Tests.Visual.OnlinePlay; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class MultiplayerSubScreenTestScene : OnlinePlayTestScene, IMultiplayerRoomTestDependencies - { - public TestMultiplayerClient Client => RoomDependencies.Client; - public new TestMultiplayerRoomManager RoomManager => RoomDependencies.RoomManager; - - protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; - - protected override RoomTestDependencies CreateRoomDependencies() => new MultiplayerRoomTestDependencies(); - } -} diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index c76d1053b2..69dfd41e04 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -2,66 +2,51 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; -using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public abstract class MultiplayerTestScene : RoomTestScene + public abstract class MultiplayerTestScene : OnlinePlayTestScene { public const int PLAYER_1_ID = 55; public const int PLAYER_2_ID = 56; - [Cached(typeof(MultiplayerClient))] - public TestMultiplayerClient Client { get; } + public TestMultiplayerClient Client => RoomDependencies.Client; + public new TestMultiplayerRoomManager RoomManager => RoomDependencies.RoomManager; - [Cached(typeof(IRoomManager))] - public TestMultiplayerRoomManager RoomManager { get; } + protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; - [Cached] - public Bindable Filter { get; } - - [Cached] - public OngoingOperationTracker OngoingOperationTracker { get; } - - protected override Container Content => content; - private readonly TestMultiplayerRoomContainer content; + protected override RoomTestDependencies CreateRoomDependencies() => new MultiplayerRoomTestDependencies(); private readonly bool joinRoom; protected MultiplayerTestScene(bool joinRoom = true) { this.joinRoom = joinRoom; - base.Content.Add(content = new TestMultiplayerRoomContainer { RelativeSizeAxes = Axes.Both }); - - Client = content.Client; - RoomManager = content.RoomManager; - Filter = content.Filter; - OngoingOperationTracker = content.OngoingOperationTracker; } [SetUp] public new void Setup() => Schedule(() => { - RoomManager.Schedule(() => RoomManager.PartRoom()); - if (joinRoom) { - Room.Name.Value = "test name"; - Room.Playlist.Add(new PlaylistItem + var room = new Room { - Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, - Ruleset = { Value = Ruleset.Value } - }); + Name = { Value = "test name" }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo }, + Ruleset = { Value = Ruleset.Value } + } + } + }; - RoomManager.Schedule(() => RoomManager.CreateRoom(Room)); + RoomManager.CreateRoom(room); + SelectedRoom.Value = room; } }); @@ -70,7 +55,9 @@ namespace osu.Game.Tests.Visual.Multiplayer base.SetUpSteps(); if (joinRoom) + { AddUntilStep("wait for room join", () => Client.Room != null); + } } } } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs deleted file mode 100644 index 1abf4d8f5d..0000000000 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomContainer.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Online.Multiplayer; -using osu.Game.Screens.OnlinePlay; -using osu.Game.Screens.OnlinePlay.Lounge.Components; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestMultiplayerRoomContainer : Container - { - protected override Container Content => content; - private readonly Container content; - - [Cached(typeof(MultiplayerClient))] - public readonly TestMultiplayerClient Client; - - [Cached(typeof(IRoomManager))] - public readonly TestMultiplayerRoomManager RoomManager; - - [Cached] - public readonly Bindable Filter = new Bindable(new FilterCriteria()); - - [Cached] - public readonly OngoingOperationTracker OngoingOperationTracker; - - public TestMultiplayerRoomContainer() - { - RelativeSizeAxes = Axes.Both; - - RoomManager = new TestMultiplayerRoomManager(); - Client = new TestMultiplayerClient(RoomManager); - OngoingOperationTracker = new OngoingOperationTracker(); - - AddRangeInternal(new Drawable[] - { - Client, - RoomManager, - OngoingOperationTracker, - content = new Container { RelativeSizeAxes = Axes.Both } - }); - } - } -} diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs index 315be510a3..6f4a464d57 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs @@ -29,10 +29,9 @@ namespace osu.Game.Tests.Visual.Multiplayer public new readonly List Rooms = new List(); - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load() { - base.LoadComplete(); - int currentScoreId = 0; int currentRoomId = 0; int currentPlaylistItemId = 0; diff --git a/osu.Game/Tests/Visual/RoomTestScene.cs b/osu.Game/Tests/Visual/RoomTestScene.cs deleted file mode 100644 index aaf5c7624f..0000000000 --- a/osu.Game/Tests/Visual/RoomTestScene.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Online.Rooms; - -namespace osu.Game.Tests.Visual -{ - public abstract class RoomTestScene : ScreenTestScene - { - [Cached] - private readonly Bindable currentRoom = new Bindable(); - - protected Room Room => currentRoom.Value; - - private CachedModelDependencyContainer dependencies; - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); - dependencies.Model.BindTo(currentRoom); - return dependencies; - } - - [SetUp] - public void Setup() => Schedule(() => - { - currentRoom.Value = new Room(); - }); - } -} From d6ab08c95821927001a863ad2db40199fc8656a3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 15:30:23 +0900 Subject: [PATCH 034/119] Remove manual dependencies in TestSceneMultiplayerGameplayLeaderboard --- ...TestSceneMultiplayerGameplayLeaderboard.cs | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index af2f6fa5fe..9c30151f05 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -7,7 +7,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Configuration; @@ -20,6 +19,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual.Online; +using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer @@ -28,28 +28,15 @@ namespace osu.Game.Tests.Visual.Multiplayer { private const int users = 16; - [Cached(typeof(SpectatorClient))] - private TestMultiplayerSpectatorClient spectatorClient = new TestMultiplayerSpectatorClient(); + public TestMultiplayerSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; - [Cached(typeof(UserLookupCache))] - private UserLookupCache lookupCache = new TestSceneCurrentlyPlayingDisplay.TestUserLookupCache(); + public UserLookupCache LookupCache => RoomDependencies?.LookupCache; + + protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; private MultiplayerGameplayLeaderboard leaderboard; - - protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; - private OsuConfigManager config; - public TestSceneMultiplayerGameplayLeaderboard() - { - base.Content.Children = new Drawable[] - { - spectatorClient, - lookupCache, - Content - }; - } - [BackgroundDependencyLoader] private void load() { @@ -59,7 +46,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUpSteps] public override void SetUpSteps() { - AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = lookupCache.GetUserAsync(1).Result); + AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).Result); AddStep("create leaderboard", () => { @@ -71,12 +58,12 @@ namespace osu.Game.Tests.Visual.Multiplayer var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); for (int i = 0; i < users; i++) - spectatorClient.StartPlay(i, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); + SpectatorClient.StartPlay(i, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - spectatorClient.Schedule(() => + SpectatorClient.Schedule(() => { Client.CurrentMatchPlayingUserIds.Clear(); - Client.CurrentMatchPlayingUserIds.AddRange(spectatorClient.PlayingUsers); + Client.CurrentMatchPlayingUserIds.AddRange(SpectatorClient.PlayingUsers); }); Children = new Drawable[] @@ -86,7 +73,7 @@ namespace osu.Game.Tests.Visual.Multiplayer scoreProcessor.ApplyBeatmap(playable); - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, spectatorClient.PlayingUsers.ToArray()) + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, SpectatorClient.PlayingUsers.ToArray()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -100,7 +87,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestScoreUpdates() { - AddRepeatStep("update state", () => spectatorClient.RandomlyUpdateState(), 100); + AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 100); AddToggleStep("switch compact mode", expanded => leaderboard.Expanded.Value = expanded); } @@ -113,11 +100,25 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestChangeScoringMode() { - AddRepeatStep("update state", () => spectatorClient.RandomlyUpdateState(), 5); + AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 5); AddStep("change to classic", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Classic)); AddStep("change to standardised", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised)); } + protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + + protected class TestDependencies : MultiplayerRoomTestDependencies + { + public readonly TestMultiplayerSpectatorClient SpectatorClient = new TestMultiplayerSpectatorClient(); + public readonly UserLookupCache LookupCache = new TestSceneCurrentlyPlayingDisplay.TestUserLookupCache(); + + public TestDependencies() + { + CacheAs(SpectatorClient); + CacheAs(LookupCache); + } + } + public class TestMultiplayerSpectatorClient : TestSpectatorClient { private readonly Dictionary lastHeaders = new Dictionary(); From 7aefbe3da16c3abecb1cfa172f4aa18a0bb329a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 17:37:02 +0900 Subject: [PATCH 035/119] Move UserLookupCache inside dependencies --- .../Visual/Gameplay/TestSceneSpectator.cs | 11 -------- .../TestSceneMultiSpectatorLeaderboard.cs | 18 ------------- .../TestSceneMultiSpectatorScreen.cs | 18 ------------- ...TestSceneMultiplayerGameplayLeaderboard.cs | 25 +++++++------------ ...ies.cs => IMultiplayerTestDependencies.cs} | 8 +++++- .../MultiplayerRoomTestDependencies.cs | 7 +++++- .../Multiplayer/MultiplayerTestScene.cs | 3 ++- ...cies.cs => IOnlinePlayTestDependencies.cs} | 2 +- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 2 +- .../Visual/OnlinePlay/RoomTestDependencies.cs | 2 +- osu.Game/Tests/Visual/TestUserLookupCache.cs | 19 ++++++++++++++ 11 files changed, 46 insertions(+), 69 deletions(-) rename osu.Game/Tests/Visual/Multiplayer/{IMultiplayerRoomTestDependencies.cs => IMultiplayerTestDependencies.cs} (71%) rename osu.Game/Tests/Visual/OnlinePlay/{IRoomTestDependencies.cs => IOnlinePlayTestDependencies.cs} (95%) create mode 100644 osu.Game/Tests/Visual/TestUserLookupCache.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 6eeb3596a8..7f3056771d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using System.Threading; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -232,14 +230,5 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("load screen", () => LoadScreen(spectatorScreen = new SoloSpectator(streamingUser))); AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded); } - - internal class TestUserLookupCache : UserLookupCache - { - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) => Task.FromResult(new User - { - Id = lookup, - Username = $"User {lookup}" - }); - } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 54594fbfc8..7f586009a1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -3,19 +3,15 @@ using System.Collections.Generic; using System.Linq; -using System.Threading; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Testing; using osu.Framework.Timing; -using osu.Game.Database; using osu.Game.Online.Spectator; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; -using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -128,24 +124,10 @@ namespace osu.Game.Tests.Visual.Multiplayer protected class TestDependencies : MultiplayerRoomTestDependencies { public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); - public readonly UserLookupCache LookupCache = new TestUserLookupCache(); public TestDependencies() { CacheAs(SpectatorClient); - CacheAs(LookupCache); - } - } - - private class TestUserLookupCache : UserLookupCache - { - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) - { - return Task.FromResult(new User - { - Id = lookup, - Username = $"User {lookup}" - }); } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 64f4b4c0d6..e6634a598e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -3,21 +3,17 @@ using System.Collections.Generic; using System.Linq; -using System.Threading; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Online.Spectator; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; -using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -289,24 +285,10 @@ namespace osu.Game.Tests.Visual.Multiplayer protected class TestDependencies : MultiplayerRoomTestDependencies { public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); - public readonly UserLookupCache LookupCache = new TestUserLookupCache(); public TestDependencies() { CacheAs(SpectatorClient); - CacheAs(LookupCache); - } - } - - internal class TestUserLookupCache : UserLookupCache - { - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) - { - return Task.FromResult(new User - { - Id = lookup, - Username = $"User {lookup}" - }); } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 9c30151f05..ae0938ae37 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -6,11 +6,11 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Configuration; -using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.Spectator; using osu.Game.Replays.Legacy; @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; -using osu.Game.Tests.Visual.Online; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; @@ -26,12 +25,10 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerGameplayLeaderboard : MultiplayerTestScene { - private const int users = 16; + private static IEnumerable users => Enumerable.Range(0, 16); public TestMultiplayerSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; - public UserLookupCache LookupCache => RoomDependencies?.LookupCache; - protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; private MultiplayerGameplayLeaderboard leaderboard; @@ -57,14 +54,11 @@ namespace osu.Game.Tests.Visual.Multiplayer var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); - for (int i = 0; i < users; i++) - SpectatorClient.StartPlay(i, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); + foreach (var user in users) + SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0); - SpectatorClient.Schedule(() => - { - Client.CurrentMatchPlayingUserIds.Clear(); - Client.CurrentMatchPlayingUserIds.AddRange(SpectatorClient.PlayingUsers); - }); + // Todo: This is REALLY bad. + Client.CurrentMatchPlayingUserIds.AddRange(users); Children = new Drawable[] { @@ -73,7 +67,7 @@ namespace osu.Game.Tests.Visual.Multiplayer scoreProcessor.ApplyBeatmap(playable); - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, SpectatorClient.PlayingUsers.ToArray()) + LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, users.ToArray()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -94,7 +88,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestUserQuit() { - AddRepeatStep("mark user quit", () => Client.CurrentMatchPlayingUserIds.RemoveAt(0), users); + foreach (var user in users) + AddStep($"mark user {user} quit", () => Client.RemoveUser(LookupCache.GetUserAsync(user).Result.AsNonNull())); } [Test] @@ -110,12 +105,10 @@ namespace osu.Game.Tests.Visual.Multiplayer protected class TestDependencies : MultiplayerRoomTestDependencies { public readonly TestMultiplayerSpectatorClient SpectatorClient = new TestMultiplayerSpectatorClient(); - public readonly UserLookupCache LookupCache = new TestSceneCurrentlyPlayingDisplay.TestUserLookupCache(); public TestDependencies() { CacheAs(SpectatorClient); - CacheAs(LookupCache); } } diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs similarity index 71% rename from osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs rename to osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs index 0b53bdd04e..331c4dcba6 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs @@ -1,13 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Database; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public interface IMultiplayerRoomTestDependencies : IRoomTestDependencies + public interface IMultiplayerTestDependencies : IOnlinePlayTestDependencies { /// /// The cached . @@ -18,5 +19,10 @@ namespace osu.Game.Tests.Visual.Multiplayer /// The cached . /// new TestMultiplayerRoomManager RoomManager { get; } + + /// + /// The cached . + /// + TestUserLookupCache LookupCache { get; } } } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs index e3913dd291..369563c5d9 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs @@ -1,21 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Database; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class MultiplayerRoomTestDependencies : RoomTestDependencies, IMultiplayerRoomTestDependencies + public class MultiplayerRoomTestDependencies : RoomTestDependencies, IMultiplayerTestDependencies { public TestMultiplayerClient Client { get; } + public TestUserLookupCache LookupCache { get; } public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; public MultiplayerRoomTestDependencies() { Client = new TestMultiplayerClient(RoomManager); + LookupCache = new TestUserLookupCache(); + CacheAs(Client); + CacheAs(LookupCache); } protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 69dfd41e04..5c717bfb2f 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -8,13 +8,14 @@ using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public abstract class MultiplayerTestScene : OnlinePlayTestScene + public abstract class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestDependencies { public const int PLAYER_1_ID = 55; public const int PLAYER_2_ID = 56; public TestMultiplayerClient Client => RoomDependencies.Client; public new TestMultiplayerRoomManager RoomManager => RoomDependencies.RoomManager; + public TestUserLookupCache LookupCache => RoomDependencies?.LookupCache; protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; diff --git a/osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs similarity index 95% rename from osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs rename to osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs index 848e2aa77f..a4e0368adc 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { - public interface IRoomTestDependencies + public interface IOnlinePlayTestDependencies { /// /// The cached . diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 5e46ea0544..39ce219092 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// A providing all the dependencies cached by for testing s. /// - public abstract class OnlinePlayTestScene : ScreenTestScene, IRoomTestDependencies + public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestDependencies { public Bindable SelectedRoom => RoomDependencies?.SelectedRoom; public IRoomManager RoomManager => RoomDependencies?.RoomManager; diff --git a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs index 9d22f9e286..b833a9400f 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// Contains dependencies for testing online-play rooms. /// - public class RoomTestDependencies : IReadOnlyDependencyContainer, IRoomTestDependencies + public class RoomTestDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies { public Bindable SelectedRoom { get; } public IRoomManager RoomManager { get; } diff --git a/osu.Game/Tests/Visual/TestUserLookupCache.cs b/osu.Game/Tests/Visual/TestUserLookupCache.cs new file mode 100644 index 0000000000..d2941b5bd5 --- /dev/null +++ b/osu.Game/Tests/Visual/TestUserLookupCache.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading; +using System.Threading.Tasks; +using osu.Game.Database; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + public class TestUserLookupCache : UserLookupCache + { + protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) => Task.FromResult(new User + { + Id = lookup, + Username = $"User {lookup}" + }); + } +} From c0d2b41d4c54fa861b9945dd9b26795b064478da Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 17:55:16 +0900 Subject: [PATCH 036/119] Move SpectatorClient into multiplayer dependencies --- .../TestSceneMultiSpectatorLeaderboard.cs | 19 ------------------- .../TestSceneMultiSpectatorScreen.cs | 19 ------------------- ...TestSceneMultiplayerGameplayLeaderboard.cs | 11 ++--------- .../TestSceneMultiplayerRoomManager.cs | 1 + .../IMultiplayerTestDependencies.cs | 6 ++++++ .../MultiplayerRoomTestDependencies.cs | 8 ++++++++ .../Multiplayer/MultiplayerTestScene.cs | 2 ++ 7 files changed, 19 insertions(+), 47 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 7f586009a1..2537198503 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -6,21 +6,14 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Testing; using osu.Framework.Timing; -using osu.Game.Online.Spectator; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play.HUD; -using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene { - public TestSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; - - protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; - private Dictionary clocks; private MultiSpectatorLeaderboard leaderboard; @@ -118,17 +111,5 @@ namespace osu.Game.Tests.Visual.Multiplayer private void assertCombo(int userId, int expectedCombo) => AddUntilStep($"player {userId} has {expectedCombo} combo", () => this.ChildrenOfType().Single(s => s.User?.Id == userId).Combo.Value == expectedCombo); - - protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); - - protected class TestDependencies : MultiplayerRoomTestDependencies - { - public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); - - public TestDependencies() - { - CacheAs(SpectatorClient); - } - } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index e6634a598e..873f8ca35b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -8,21 +8,14 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Online.Spectator; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps.IO; -using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiSpectatorScreen : MultiplayerTestScene { - public TestSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; - - protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; - [Resolved] private OsuGameBase game { get; set; } @@ -279,17 +272,5 @@ namespace osu.Game.Tests.Visual.Multiplayer private Player getPlayer(int userId) => getInstance(userId).ChildrenOfType().Single(); private PlayerArea getInstance(int userId) => spectatorScreen.ChildrenOfType().Single(p => p.UserId == userId); - - protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); - - protected class TestDependencies : MultiplayerRoomTestDependencies - { - public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); - - public TestDependencies() - { - CacheAs(SpectatorClient); - } - } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index ae0938ae37..b7ccc17397 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -27,9 +27,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { private static IEnumerable users => Enumerable.Range(0, 16); - public TestMultiplayerSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; - - protected new TestDependencies RoomDependencies => (TestDependencies)base.RoomDependencies; + public new TestMultiplayerSpectatorClient SpectatorClient => (TestMultiplayerSpectatorClient)RoomDependencies?.SpectatorClient; private MultiplayerGameplayLeaderboard leaderboard; private OsuConfigManager config; @@ -104,12 +102,7 @@ namespace osu.Game.Tests.Visual.Multiplayer protected class TestDependencies : MultiplayerRoomTestDependencies { - public readonly TestMultiplayerSpectatorClient SpectatorClient = new TestMultiplayerSpectatorClient(); - - public TestDependencies() - { - CacheAs(SpectatorClient); - } + protected override TestSpectatorClient CreateSpectatorClient() => new TestMultiplayerSpectatorClient(); } public class TestMultiplayerSpectatorClient : TestSpectatorClient diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index 302e6998cc..225a9ff703 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -148,6 +148,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public TestDependencies() { + // Need to set these values as early as possible. RoomManager.TimeBetweenListingPolls.Value = 1; RoomManager.TimeBetweenSelectionPolls.Value = 1; } diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs index 331c4dcba6..c5f9e85003 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs @@ -5,6 +5,7 @@ using osu.Game.Database; using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; +using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { @@ -24,5 +25,10 @@ namespace osu.Game.Tests.Visual.Multiplayer /// The cached . /// TestUserLookupCache LookupCache { get; } + + /// + /// The cached . + /// + TestSpectatorClient SpectatorClient { get; } } } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs index 369563c5d9..a3f7156848 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs @@ -3,8 +3,10 @@ using osu.Game.Database; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Spectator; using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; +using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { @@ -12,17 +14,23 @@ namespace osu.Game.Tests.Visual.Multiplayer { public TestMultiplayerClient Client { get; } public TestUserLookupCache LookupCache { get; } + public TestSpectatorClient SpectatorClient { get; } + public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; public MultiplayerRoomTestDependencies() { Client = new TestMultiplayerClient(RoomManager); LookupCache = new TestUserLookupCache(); + SpectatorClient = CreateSpectatorClient(); CacheAs(Client); CacheAs(LookupCache); + CacheAs(SpectatorClient); } protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); + + protected virtual TestSpectatorClient CreateSpectatorClient() => new TestSpectatorClient(); } } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 5c717bfb2f..19e7536286 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Game.Online.Rooms; using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.OnlinePlay; +using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { @@ -16,6 +17,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public TestMultiplayerClient Client => RoomDependencies.Client; public new TestMultiplayerRoomManager RoomManager => RoomDependencies.RoomManager; public TestUserLookupCache LookupCache => RoomDependencies?.LookupCache; + public TestSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; From 04279e7f5cbfa0a90982f4cfb333be8f0e99f4b0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 18:02:53 +0900 Subject: [PATCH 037/119] Add some xmldocs --- .../Visual/Multiplayer/IMultiplayerTestDependencies.cs | 3 +++ .../Multiplayer/MultiplayerRoomTestDependencies.cs | 4 +++- .../Tests/Visual/Multiplayer/MultiplayerTestScene.cs | 9 +++++---- .../Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 3 +++ .../Visual/Multiplayer/TestMultiplayerRoomManager.cs | 4 ++++ osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs | 4 ++++ .../Visual/OnlinePlay/IOnlinePlayTestDependencies.cs | 3 +++ osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs | 2 +- osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs | 2 +- 9 files changed, 27 insertions(+), 7 deletions(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs index c5f9e85003..46ad5a5a1c 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs @@ -9,6 +9,9 @@ using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { + /// + /// Interface that defines the dependencies required for multiplayer test scenes. + /// public interface IMultiplayerTestDependencies : IOnlinePlayTestDependencies { /// diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs index a3f7156848..4c5afb9b58 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs @@ -10,12 +10,14 @@ using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { + /// + /// Contains the basic dependencies of multiplayer test scenes. + /// public class MultiplayerRoomTestDependencies : RoomTestDependencies, IMultiplayerTestDependencies { public TestMultiplayerClient Client { get; } public TestUserLookupCache LookupCache { get; } public TestSpectatorClient SpectatorClient { get; } - public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; public MultiplayerRoomTestDependencies() diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 19e7536286..6a9ae4c772 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -9,6 +9,9 @@ using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { + /// + /// The base test scene for all multiplayer components and screens. + /// public abstract class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestDependencies { public const int PLAYER_1_ID = 55; @@ -21,8 +24,6 @@ namespace osu.Game.Tests.Visual.Multiplayer protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; - protected override RoomTestDependencies CreateRoomDependencies() => new MultiplayerRoomTestDependencies(); - private readonly bool joinRoom; protected MultiplayerTestScene(bool joinRoom = true) @@ -58,9 +59,9 @@ namespace osu.Game.Tests.Visual.Multiplayer base.SetUpSteps(); if (joinRoom) - { AddUntilStep("wait for room join", () => Client.Room != null); - } } + + protected override RoomTestDependencies CreateRoomDependencies() => new MultiplayerRoomTestDependencies(); } } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index b12bd8091d..b0c8d6d19b 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -20,6 +20,9 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { + /// + /// A for use in multiplayer test scenes. Should generally not be used by itself outside of a . + /// public class TestMultiplayerClient : MultiplayerClient { public override IBindable IsConnected => isConnected; diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs index 6f4a464d57..5d66cdba02 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs @@ -11,11 +11,15 @@ using osu.Game.Online.API.Requests; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; namespace osu.Game.Tests.Visual.Multiplayer { + /// + /// A for use in multiplayer test scenes. Should generally not be used by itself outside of a . + /// public class TestMultiplayerRoomManager : MultiplayerRoomManager { [Resolved] diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index 67beea9117..81b93fe5b5 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -8,10 +8,14 @@ using osu.Game.Beatmaps; using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Screens.OnlinePlay; +using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Users; namespace osu.Game.Tests.Visual.OnlinePlay { + /// + /// A very simple for use in online-play test scenes. + /// public class BasicTestRoomManager : IRoomManager { public event Action RoomsUpdated diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs index a4e0368adc..bc5d524bc4 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs @@ -8,6 +8,9 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { + /// + /// Interface that defines the dependencies required for online-play test scenes. + /// public interface IOnlinePlayTestDependencies { /// diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 39ce219092..6c1339fd85 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -14,7 +14,7 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// A providing all the dependencies cached by for testing s. + /// A base test scene for all online-play components and screens. /// public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestDependencies { diff --git a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs index b833a9400f..7b198c128b 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs @@ -13,7 +13,7 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// Contains dependencies for testing online-play rooms. + /// Contains the basic dependencies of online-play test scenes. /// public class RoomTestDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies { From a27a647ae72a7610caa442af2c293db494ccf9ae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 18:07:47 +0900 Subject: [PATCH 038/119] Rename RoomDependencies -> OnlinePlayDependencies --- ...TestSceneMultiplayerGameplayLeaderboard.cs | 4 +- .../TestSceneMultiplayerRoomManager.cs | 2 +- .../TestScenePlaylistsMatchSettingsOverlay.cs | 4 +- .../MultiplayerRoomTestDependencies.cs | 2 +- .../Multiplayer/MultiplayerTestScene.cs | 12 ++--- .../Visual/OnlinePlay/BasicTestRoomManager.cs | 2 +- .../OnlinePlay/IOnlinePlayTestDependencies.cs | 2 +- ...ncies.cs => OnlinePlayTestDependencies.cs} | 6 +-- .../Visual/OnlinePlay/OnlinePlayTestScene.cs | 50 ++++++++++--------- 9 files changed, 44 insertions(+), 40 deletions(-) rename osu.Game/Tests/Visual/OnlinePlay/{RoomTestDependencies.cs => OnlinePlayTestDependencies.cs} (92%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index b7ccc17397..2938e813b2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { private static IEnumerable users => Enumerable.Range(0, 16); - public new TestMultiplayerSpectatorClient SpectatorClient => (TestMultiplayerSpectatorClient)RoomDependencies?.SpectatorClient; + public new TestMultiplayerSpectatorClient SpectatorClient => (TestMultiplayerSpectatorClient)OnlinePlayDependencies?.SpectatorClient; private MultiplayerGameplayLeaderboard leaderboard; private OsuConfigManager config; @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("change to standardised", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised)); } - protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new TestDependencies(); protected class TestDependencies : MultiplayerRoomTestDependencies { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index 225a9ff703..c750bbed4b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [HeadlessTest] public class TestSceneMultiplayerRoomManager : MultiplayerTestScene { - protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new TestDependencies(); public TestSceneMultiplayerRoomManager() : base(false) diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index b52b6a6a0e..fd59ebad30 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Playlists private TestRoomSettings settings; - protected override RoomTestDependencies CreateRoomDependencies() => new TestDependencies(); + protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new TestDependencies(); [SetUp] public new void Setup() => Schedule(() => @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Playlists public OsuSpriteText ErrorText => ((MatchSettings)Settings).ErrorText; } - private class TestDependencies : RoomTestDependencies + private class TestDependencies : OnlinePlayTestDependencies { protected override IRoomManager CreateRoomManager() => new TestRoomManager(); } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs index 4c5afb9b58..e7885890b4 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// Contains the basic dependencies of multiplayer test scenes. /// - public class MultiplayerRoomTestDependencies : RoomTestDependencies, IMultiplayerTestDependencies + public class MultiplayerRoomTestDependencies : OnlinePlayTestDependencies, IMultiplayerTestDependencies { public TestMultiplayerClient Client { get; } public TestUserLookupCache LookupCache { get; } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 6a9ae4c772..90ffc83ccd 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -17,12 +17,12 @@ namespace osu.Game.Tests.Visual.Multiplayer public const int PLAYER_1_ID = 55; public const int PLAYER_2_ID = 56; - public TestMultiplayerClient Client => RoomDependencies.Client; - public new TestMultiplayerRoomManager RoomManager => RoomDependencies.RoomManager; - public TestUserLookupCache LookupCache => RoomDependencies?.LookupCache; - public TestSpectatorClient SpectatorClient => RoomDependencies?.SpectatorClient; + public TestMultiplayerClient Client => OnlinePlayDependencies.Client; + public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager; + public TestUserLookupCache LookupCache => OnlinePlayDependencies?.LookupCache; + public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient; - protected new MultiplayerRoomTestDependencies RoomDependencies => (MultiplayerRoomTestDependencies)base.RoomDependencies; + protected new MultiplayerRoomTestDependencies OnlinePlayDependencies => (MultiplayerRoomTestDependencies)base.OnlinePlayDependencies; private readonly bool joinRoom; @@ -62,6 +62,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for room join", () => Client.Room != null); } - protected override RoomTestDependencies CreateRoomDependencies() => new MultiplayerRoomTestDependencies(); + protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new MultiplayerRoomTestDependencies(); } } diff --git a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs index 81b93fe5b5..813e617ac5 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/BasicTestRoomManager.cs @@ -14,7 +14,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// A very simple for use in online-play test scenes. + /// A very simple for use in online play test scenes. /// public class BasicTestRoomManager : IRoomManager { diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs index bc5d524bc4..8c262e718a 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs @@ -9,7 +9,7 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// Interface that defines the dependencies required for online-play test scenes. + /// Interface that defines the dependencies required for online play test scenes. /// public interface IOnlinePlayTestDependencies { diff --git a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestDependencies.cs similarity index 92% rename from osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs rename to osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestDependencies.cs index 7b198c128b..e45aadfd84 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/RoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestDependencies.cs @@ -13,9 +13,9 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// Contains the basic dependencies of online-play test scenes. + /// Contains the basic dependencies of online play test scenes. /// - public class RoomTestDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies + public class OnlinePlayTestDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies { public Bindable SelectedRoom { get; } public IRoomManager RoomManager { get; } @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay private readonly List drawableComponents = new List(); private readonly DependencyContainer dependencies; - public RoomTestDependencies() + public OnlinePlayTestDependencies() { SelectedRoom = new Bindable(); RoomManager = CreateRoomManager(); diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 6c1339fd85..e1c21ce377 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -14,18 +14,22 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; namespace osu.Game.Tests.Visual.OnlinePlay { /// - /// A base test scene for all online-play components and screens. + /// A base test scene for all online play components and screens. /// public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestDependencies { - public Bindable SelectedRoom => RoomDependencies?.SelectedRoom; - public IRoomManager RoomManager => RoomDependencies?.RoomManager; - public Bindable Filter => RoomDependencies?.Filter; - public OngoingOperationTracker OngoingOperationTracker => RoomDependencies?.OngoingOperationTracker; - public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => RoomDependencies?.AvailabilityTracker; + public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; + public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; + public Bindable Filter => OnlinePlayDependencies?.Filter; + public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker; + public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker; - protected RoomTestDependencies RoomDependencies => delegatedDependencies?.RoomDependencies; - private DelegatedRoomDependencyContainer delegatedDependencies; + /// + /// All dependencies required for online play components and screens. + /// + protected OnlinePlayTestDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies; + + private DelegatedDependencyContainer dependencies; protected override Container Content => content; private readonly Container content; @@ -42,8 +46,8 @@ namespace osu.Game.Tests.Visual.OnlinePlay protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - delegatedDependencies = new DelegatedRoomDependencyContainer(base.CreateChildDependencies(parent)); - return delegatedDependencies; + dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent)); + return dependencies; } [SetUp] @@ -51,46 +55,46 @@ namespace osu.Game.Tests.Visual.OnlinePlay { // Reset the room dependencies to a fresh state. drawableDependenciesContainer.Clear(); - delegatedDependencies.RoomDependencies = CreateRoomDependencies(); - drawableDependenciesContainer.AddRange(RoomDependencies.DrawableComponents); + dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies(); + drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents); }); /// /// Creates the room dependencies. Called every . /// /// - /// Any custom dependencies required for online-play sub-classes should be added here. + /// Any custom dependencies required for online play sub-classes should be added here. /// - protected virtual RoomTestDependencies CreateRoomDependencies() => new RoomTestDependencies(); + protected virtual OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new OnlinePlayTestDependencies(); /// - /// A providing a mutable lookup source for room dependencies. + /// A providing a mutable lookup source for online play dependencies. /// - private class DelegatedRoomDependencyContainer : IReadOnlyDependencyContainer + private class DelegatedDependencyContainer : IReadOnlyDependencyContainer { /// - /// The room's dependencies. + /// The online play dependencies. /// - public RoomTestDependencies RoomDependencies { get; set; } + public OnlinePlayTestDependencies OnlinePlayDependencies { get; set; } private readonly IReadOnlyDependencyContainer parent; private readonly DependencyContainer injectableDependencies; /// - /// Creates a new . + /// Creates a new . /// - /// The fallback to use when cannot satisfy a dependency. - public DelegatedRoomDependencyContainer(IReadOnlyDependencyContainer parent) + /// The fallback to use when cannot satisfy a dependency. + public DelegatedDependencyContainer(IReadOnlyDependencyContainer parent) { this.parent = parent; injectableDependencies = new DependencyContainer(this); } public object Get(Type type) - => RoomDependencies?.Get(type) ?? parent.Get(type); + => OnlinePlayDependencies?.Get(type) ?? parent.Get(type); public object Get(Type type, CacheInfo info) - => RoomDependencies?.Get(type, info) ?? parent.Get(type, info); + => OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info); public void Inject(T instance) where T : class From 04cc390c419f73da5bc074fe0ef168f594e51a7f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 19:16:54 +0900 Subject: [PATCH 039/119] Fix TestSceneMultiplayer resolving the wrong client --- .../Multiplayer/TestSceneMultiplayer.cs | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 599dfb082b..c93640e7b5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -18,6 +18,7 @@ using osu.Game.Overlays.Mods; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Match.Components; using osu.Game.Screens.OnlinePlay.Multiplayer; @@ -30,14 +31,13 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayer : ScreenTestScene { - private TestMultiplayer multiplayerScreen; - private BeatmapManager beatmaps; private RulesetStore rulesets; private BeatmapSetInfo importedSet; - private TestMultiplayerClient client => multiplayerScreen.Client; - private Room room => client.APIRoom; + private DependenciesScreen dependenciesScreen; + private TestMultiplayer multiplayerScreen; + private TestMultiplayerClient client; public TestSceneMultiplayer() { @@ -229,30 +229,43 @@ namespace osu.Game.Tests.Visual.Multiplayer private void loadMultiplayer() { - AddStep("show", () => + AddStep("create multiplayer screen", () => multiplayerScreen = new TestMultiplayer()); + + AddStep("load dependencies", () => { - multiplayerScreen = new TestMultiplayer(); + client = new TestMultiplayerClient(multiplayerScreen.RoomManager); - // Needs to be added at a higher level since the multiplayer screen becomes non-current. - Child = multiplayerScreen.Client; + // The screen gets suspended so it stops receiving updates. + Child = client; - LoadScreen(multiplayerScreen); + LoadScreen(dependenciesScreen = new DependenciesScreen(client)); }); - AddUntilStep("wait for loaded", () => multiplayerScreen.IsLoaded); + AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded); + + AddStep("load multiplayer", () => LoadScreen(multiplayerScreen)); + AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded); } - private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer + /// + /// Used for the sole purpose of adding as a resolvable dependency. + /// + private class DependenciesScreen : OsuScreen { [Cached(typeof(MultiplayerClient))] public readonly TestMultiplayerClient Client; - public TestMultiplayer() + public DependenciesScreen(TestMultiplayerClient client) { - Client = new TestMultiplayerClient((TestMultiplayerRoomManager)RoomManager); + Client = client; } + } - protected override RoomManager CreateRoomManager() => new TestMultiplayerRoomManager(); + private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer + { + public new TestMultiplayerRoomManager RoomManager { get; private set; } + + protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager(); } } } From 57f2b4f812870bb1d9804ee7d8c079c106bd84d9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 20:09:03 +0900 Subject: [PATCH 040/119] Fix incorrect parent class --- .../Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index afe66d2686..4e08ffef17 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -5,11 +5,10 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; -using osu.Game.Tests.Visual.OnlinePlay; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerMatchFooter : OnlinePlayTestScene + public class TestSceneMultiplayerMatchFooter : MultiplayerTestScene { [SetUp] public new void Setup() => Schedule(() => From 1ed61b9b98757b1c2b63a1127c3569f0d728624a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 20:11:38 +0900 Subject: [PATCH 041/119] Fix up dependencies class names --- .../Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs | 4 ++-- .../Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs | 4 ++-- .../Playlists/TestScenePlaylistsMatchSettingsOverlay.cs | 4 ++-- osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs | 4 ++-- ...tDependencies.cs => MultiplayerTestSceneDependencies.cs} | 4 ++-- osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs | 6 +++--- ...stDependencies.cs => OnlinePlayTestSceneDependencies.cs} | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) rename osu.Game/Tests/Visual/Multiplayer/{MultiplayerRoomTestDependencies.cs => MultiplayerTestSceneDependencies.cs} (89%) rename osu.Game/Tests/Visual/OnlinePlay/{OnlinePlayTestDependencies.cs => OnlinePlayTestSceneDependencies.cs} (94%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 2938e813b2..0e368b59dd 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -98,9 +98,9 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("change to standardised", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised)); } - protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new TestDependencies(); + protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); - protected class TestDependencies : MultiplayerRoomTestDependencies + protected class TestDependencies : MultiplayerTestSceneDependencies { protected override TestSpectatorClient CreateSpectatorClient() => new TestMultiplayerSpectatorClient(); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index c750bbed4b..b17427a30b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [HeadlessTest] public class TestSceneMultiplayerRoomManager : MultiplayerTestScene { - protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new TestDependencies(); + protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); public TestSceneMultiplayerRoomManager() : base(false) @@ -144,7 +144,7 @@ namespace osu.Game.Tests.Visual.Multiplayer return room; } - private class TestDependencies : MultiplayerRoomTestDependencies + private class TestDependencies : MultiplayerTestSceneDependencies { public TestDependencies() { diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index fd59ebad30..a320cb240f 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Playlists private TestRoomSettings settings; - protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new TestDependencies(); + protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); [SetUp] public new void Setup() => Schedule(() => @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Playlists public OsuSpriteText ErrorText => ((MatchSettings)Settings).ErrorText; } - private class TestDependencies : OnlinePlayTestDependencies + private class TestDependencies : OnlinePlayTestSceneDependencies { protected override IRoomManager CreateRoomManager() => new TestRoomManager(); } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index 90ffc83ccd..da01010dbf 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public TestUserLookupCache LookupCache => OnlinePlayDependencies?.LookupCache; public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient; - protected new MultiplayerRoomTestDependencies OnlinePlayDependencies => (MultiplayerRoomTestDependencies)base.OnlinePlayDependencies; + protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies; private readonly bool joinRoom; @@ -62,6 +62,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for room join", () => Client.Room != null); } - protected override OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new MultiplayerRoomTestDependencies(); + protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new MultiplayerTestSceneDependencies(); } } diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs similarity index 89% rename from osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs rename to osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index e7885890b4..8fd21b5e4a 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerRoomTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -13,14 +13,14 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// Contains the basic dependencies of multiplayer test scenes. /// - public class MultiplayerRoomTestDependencies : OnlinePlayTestDependencies, IMultiplayerTestDependencies + public class MultiplayerTestSceneDependencies : OnlinePlayTestSceneDependencies, IMultiplayerTestDependencies { public TestMultiplayerClient Client { get; } public TestUserLookupCache LookupCache { get; } public TestSpectatorClient SpectatorClient { get; } public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; - public MultiplayerRoomTestDependencies() + public MultiplayerTestSceneDependencies() { Client = new TestMultiplayerClient(RoomManager); LookupCache = new TestUserLookupCache(); diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index e1c21ce377..4920ca2058 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// All dependencies required for online play components and screens. /// - protected OnlinePlayTestDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies; + protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies; private DelegatedDependencyContainer dependencies; @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// Any custom dependencies required for online play sub-classes should be added here. /// - protected virtual OnlinePlayTestDependencies CreateOnlinePlayDependencies() => new OnlinePlayTestDependencies(); + protected virtual OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new OnlinePlayTestSceneDependencies(); /// /// A providing a mutable lookup source for online play dependencies. @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// The online play dependencies. /// - public OnlinePlayTestDependencies OnlinePlayDependencies { get; set; } + public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; } private readonly IReadOnlyDependencyContainer parent; private readonly DependencyContainer injectableDependencies; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs similarity index 94% rename from osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestDependencies.cs rename to osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index e45aadfd84..b73a982fb6 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// Contains the basic dependencies of online play test scenes. /// - public class OnlinePlayTestDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies + public class OnlinePlayTestSceneDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies { public Bindable SelectedRoom { get; } public IRoomManager RoomManager { get; } @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay private readonly List drawableComponents = new List(); private readonly DependencyContainer dependencies; - public OnlinePlayTestDependencies() + public OnlinePlayTestSceneDependencies() { SelectedRoom = new Bindable(); RoomManager = CreateRoomManager(); From c93c615f5e704d248f82fecb1f6fdda06e248aed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 20:15:30 +0900 Subject: [PATCH 042/119] Also fix up interface names --- ...TestDependencies.cs => IMultiplayerTestSceneDependencies.cs} | 2 +- osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs | 2 +- .../Visual/Multiplayer/MultiplayerTestSceneDependencies.cs | 2 +- ...yTestDependencies.cs => IOnlinePlayTestSceneDependencies.cs} | 2 +- osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs | 2 +- .../Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename osu.Game/Tests/Visual/Multiplayer/{IMultiplayerTestDependencies.cs => IMultiplayerTestSceneDependencies.cs} (92%) rename osu.Game/Tests/Visual/OnlinePlay/{IOnlinePlayTestDependencies.cs => IOnlinePlayTestSceneDependencies.cs} (95%) diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs similarity index 92% rename from osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs rename to osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs index 46ad5a5a1c..204c189591 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// Interface that defines the dependencies required for multiplayer test scenes. /// - public interface IMultiplayerTestDependencies : IOnlinePlayTestDependencies + public interface IMultiplayerTestSceneDependencies : IOnlinePlayTestSceneDependencies { /// /// The cached . diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index da01010dbf..b7d3793ab1 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// The base test scene for all multiplayer components and screens. /// - public abstract class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestDependencies + public abstract class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestSceneDependencies { public const int PLAYER_1_ID = 55; public const int PLAYER_2_ID = 56; diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index 8fd21b5e4a..a2b0b066a7 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// Contains the basic dependencies of multiplayer test scenes. /// - public class MultiplayerTestSceneDependencies : OnlinePlayTestSceneDependencies, IMultiplayerTestDependencies + public class MultiplayerTestSceneDependencies : OnlinePlayTestSceneDependencies, IMultiplayerTestSceneDependencies { public TestMultiplayerClient Client { get; } public TestUserLookupCache LookupCache { get; } diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs similarity index 95% rename from osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs rename to osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index 8c262e718a..6e1e831d9b 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -11,7 +11,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// Interface that defines the dependencies required for online play test scenes. /// - public interface IOnlinePlayTestDependencies + public interface IOnlinePlayTestSceneDependencies { /// /// The cached . diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index 4920ca2058..997c910dd4 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// A base test scene for all online play components and screens. /// - public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestDependencies + public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies { public Bindable SelectedRoom => OnlinePlayDependencies?.SelectedRoom; public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index b73a982fb6..ddbbfe501b 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay /// /// Contains the basic dependencies of online play test scenes. /// - public class OnlinePlayTestSceneDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestDependencies + public class OnlinePlayTestSceneDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestSceneDependencies { public Bindable SelectedRoom { get; } public IRoomManager RoomManager { get; } From 3e5ae7ea58090d9b30d31cbb52ccb2dfd68fe45a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 20:44:00 +0900 Subject: [PATCH 043/119] Don't join room in participants test --- .../Multiplayer/TestSceneMultiplayerParticipantsList.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index 7f8f04b718..e94750c695 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -22,6 +22,11 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerParticipantsList : MultiplayerTestScene { + public TestSceneMultiplayerParticipantsList() + : base(false) + { + } + [SetUp] public new void Setup() => Schedule(createNewParticipantsList); From d035633f9514d78b7dfc88a1f567220169eb061b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 25 Jun 2021 20:56:13 +0900 Subject: [PATCH 044/119] Load participants list after joining room --- .../TestSceneMultiplayerParticipantsList.cs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index e94750c695..6526f7eea7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -22,14 +22,12 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerParticipantsList : MultiplayerTestScene { - public TestSceneMultiplayerParticipantsList() - : base(false) + [SetUpSteps] + public void SetupSteps() { + createNewParticipantsList(); } - [SetUp] - public new void Setup() => Schedule(createNewParticipantsList); - [Test] public void TestAddUser() { @@ -93,7 +91,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestCorrectInitialState() { AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); - AddStep("recreate list", createNewParticipantsList); + createNewParticipantsList(); checkProgressBarVisibility(true); } @@ -238,7 +236,17 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createNewParticipantsList() { - Child = new ParticipantsList { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Y, Size = new Vector2(380, 0.7f) }; + ParticipantsList participantsList = null; + + AddStep("create new list", () => Child = participantsList = new ParticipantsList + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Size = new Vector2(380, 0.7f) + }); + + AddUntilStep("wait for list to load", () => participantsList.IsLoaded); } private void checkProgressBarVisibility(bool visible) => From e5eea503dbdfebee5f2911354ded244885a5f5d1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 26 Jun 2021 12:21:49 +0300 Subject: [PATCH 045/119] Remove finalizer logic from `ResourcesSkin` --- osu.Game/Skinning/ResourcesSkin.cs | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/osu.Game/Skinning/ResourcesSkin.cs b/osu.Game/Skinning/ResourcesSkin.cs index 3d17d7cc3d..90020495c3 100644 --- a/osu.Game/Skinning/ResourcesSkin.cs +++ b/osu.Game/Skinning/ResourcesSkin.cs @@ -19,7 +19,7 @@ namespace osu.Game.Skinning /// /// An that uses an underlying with namespaces for resources retrieval. /// - public class ResourcesSkin : ISkin + public class ResourcesSkin : ISkin, IDisposable { private readonly TextureStore textures; private readonly ISampleStore samples; @@ -48,33 +48,10 @@ namespace osu.Game.Skinning public IBindable? GetConfig(TLookup lookup) => null; - #region Disposal - - ~ResourcesSkin() - { - // required to potentially clean up sample store from audio hierarchy. - Dispose(false); - } - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - private bool isDisposed; - - protected virtual void Dispose(bool isDisposing) - { - if (isDisposed) - return; - - isDisposed = true; - textures.Dispose(); samples.Dispose(); } - - #endregion } } From e8e9fdd5331dec8d6522c23dcb7b03827b4ef666 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 26 Jun 2021 12:23:05 +0300 Subject: [PATCH 046/119] Dispose `ResourcesSkin` before clearing skin sources --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 54bf91523f..8a807eff21 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -72,6 +73,9 @@ namespace osu.Game.Skinning protected virtual void UpdateSkins() { + foreach (var resourcesSkin in SkinSources.OfType()) + resourcesSkin.Dispose(); + SkinSources.Clear(); foreach (var skin in skinSource.AllSources) From f777741ca788c3ea1a83830cd5db7286f943e67f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Jun 2021 14:51:27 +0900 Subject: [PATCH 047/119] Simplify instantiation --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 8a807eff21..a1db4ba6d1 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -96,12 +96,14 @@ namespace osu.Game.Skinning { int defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); + var rulesetResources = new ResourcesSkin(resources, host, audio); + if (defaultSkinIndex >= 0) - SkinSources.Insert(defaultSkinIndex, new ResourcesSkin(resources, host, audio)); + SkinSources.Insert(defaultSkinIndex, rulesetResources); else { // Tests may potentially override the SkinManager with another source that doesn't include it in AllSources. - SkinSources.Add(new ResourcesSkin(resources, host, audio)); + SkinSources.Add(rulesetResources); } } } From 692f24437ef5ec3afd2eed87143da90bd621c5fd Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 09:11:28 +0300 Subject: [PATCH 048/119] Maintain ruleset resources skin across multiple source changes --- .../Skinning/RulesetSkinProvidingContainer.cs | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index a1db4ba6d1..076f8b03dc 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -46,21 +46,20 @@ namespace osu.Game.Skinning }; } - [Resolved] - private GameHost host { get; set; } - - [Resolved] - private AudioManager audio { get; set; } - [Resolved] private SkinManager skinManager { get; set; } [Resolved] private ISkinSource skinSource { get; set; } + private ResourcesSkin rulesetResourcesSkin; + [BackgroundDependencyLoader] - private void load() + private void load(GameHost host, AudioManager audio) { + if (Ruleset.CreateResourceStore() is IResourceStore resources) + rulesetResourcesSkin = new ResourcesSkin(resources, host, audio); + UpdateSkins(); skinSource.SourceChanged += OnSourceChanged; } @@ -73,9 +72,6 @@ namespace osu.Game.Skinning protected virtual void UpdateSkins() { - foreach (var resourcesSkin in SkinSources.OfType()) - resourcesSkin.Dispose(); - SkinSources.Clear(); foreach (var skin in skinSource.AllSources) @@ -92,20 +88,12 @@ namespace osu.Game.Skinning } } - if (Ruleset.CreateResourceStore() is IResourceStore resources) - { - int defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); + int defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); - var rulesetResources = new ResourcesSkin(resources, host, audio); - - if (defaultSkinIndex >= 0) - SkinSources.Insert(defaultSkinIndex, rulesetResources); - else - { - // Tests may potentially override the SkinManager with another source that doesn't include it in AllSources. - SkinSources.Add(rulesetResources); - } - } + if (defaultSkinIndex >= 0) + SkinSources.Insert(defaultSkinIndex, rulesetResourcesSkin); + else + SkinSources.Add(rulesetResourcesSkin); } protected ISkin GetLegacyRulesetTransformedSkin(ISkin legacySkin) @@ -126,6 +114,8 @@ namespace osu.Game.Skinning if (skinSource != null) skinSource.SourceChanged -= OnSourceChanged; + + rulesetResourcesSkin?.Dispose(); } } } From f598de4cdb0069109abc42485349b2026ea323f8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 09:18:29 +0300 Subject: [PATCH 049/119] ResourcesSkin -> ResourceStoreBackedSkin --- .../{ResourcesSkin.cs => ResourceStoreBackedSkin.cs} | 4 ++-- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) rename osu.Game/Skinning/{ResourcesSkin.cs => ResourceStoreBackedSkin.cs} (91%) diff --git a/osu.Game/Skinning/ResourcesSkin.cs b/osu.Game/Skinning/ResourceStoreBackedSkin.cs similarity index 91% rename from osu.Game/Skinning/ResourcesSkin.cs rename to osu.Game/Skinning/ResourceStoreBackedSkin.cs index 90020495c3..f041b82cf4 100644 --- a/osu.Game/Skinning/ResourcesSkin.cs +++ b/osu.Game/Skinning/ResourceStoreBackedSkin.cs @@ -19,12 +19,12 @@ namespace osu.Game.Skinning /// /// An that uses an underlying with namespaces for resources retrieval. /// - public class ResourcesSkin : ISkin, IDisposable + public class ResourceStoreBackedSkin : ISkin, IDisposable { private readonly TextureStore textures; private readonly ISampleStore samples; - public ResourcesSkin(IResourceStore resources, GameHost host, AudioManager audio) + public ResourceStoreBackedSkin(IResourceStore resources, GameHost host, AudioManager audio) { textures = new TextureStore(host.CreateTextureLoaderStore(new NamespacedResourceStore(resources, @"Textures"))); samples = audio.GetSampleStore(new NamespacedResourceStore(resources, @"Samples")); diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 076f8b03dc..d35e9c1ff3 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -52,13 +51,13 @@ namespace osu.Game.Skinning [Resolved] private ISkinSource skinSource { get; set; } - private ResourcesSkin rulesetResourcesSkin; + private ResourceStoreBackedSkin rulesetResourcesSkin; [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) { if (Ruleset.CreateResourceStore() is IResourceStore resources) - rulesetResourcesSkin = new ResourcesSkin(resources, host, audio); + rulesetResourcesSkin = new ResourceStoreBackedSkin(resources, host, audio); UpdateSkins(); skinSource.SourceChanged += OnSourceChanged; From 779a1b322ca177632e6ba76e50cb431c40cf2600 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 09:38:42 +0300 Subject: [PATCH 050/119] Add comment explaining insertion of ruleset skin before default skin Co-authored-by: Dean Herbert --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index d35e9c1ff3..5f0ca27170 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -89,6 +89,9 @@ namespace osu.Game.Skinning int defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); + // Ruleset resources should be given the ability to override game-wide defaults + // This is achieved by placing them before an instance of DefaultSkin. + // Note that DefaultSkin may not be present in some test scenes. if (defaultSkinIndex >= 0) SkinSources.Insert(defaultSkinIndex, rulesetResourcesSkin); else From 035fe2ad4919e67be14d4fc2323d0daa10753fa2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 11:29:43 +0300 Subject: [PATCH 051/119] Mark ruleset skin provider test scene as headless --- .../Rulesets/TestSceneRulesetSkinProvidingContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs index e060c8578a..28ad7ed6a7 100644 --- a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; +using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Rulesets; using osu.Game.Skinning; @@ -18,6 +19,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Tests.Rulesets { + [HeadlessTest] public class TestSceneRulesetSkinProvidingContainer : OsuTestScene { private SkinRequester requester; From 7197998a104d0e25db060cf6adbbb4f14870bf64 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 12:43:12 +0300 Subject: [PATCH 052/119] Remove resolution to `SkinManager` and use pattern matching instead --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index c3d01218d7..26646d87fe 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -45,15 +46,12 @@ namespace osu.Game.Skinning }; } - private SkinManager skinManager; private ISkinSource parentSource; private ResourceStoreBackedSkin rulesetResourcesSkin; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - skinManager = parent.Get(); - parentSource = parent.Get(); parentSource.SourceChanged += OnSourceChanged; @@ -90,13 +88,13 @@ namespace osu.Game.Skinning } } - int defaultSkinIndex = SkinSources.IndexOf(skinManager.DefaultSkin); + int lastDefaultSkinIndex = SkinSources.IndexOf(SkinSources.OfType().Last()); // Ruleset resources should be given the ability to override game-wide defaults - // This is achieved by placing them before an instance of DefaultSkin. + // This is achieved by placing them before the last instance of DefaultSkin. // Note that DefaultSkin may not be present in some test scenes. - if (defaultSkinIndex >= 0) - SkinSources.Insert(defaultSkinIndex, rulesetResourcesSkin); + if (lastDefaultSkinIndex >= 0) + SkinSources.Insert(lastDefaultSkinIndex, rulesetResourcesSkin); else SkinSources.Add(rulesetResourcesSkin); } From 66fc95c1118f74fa9ce78d154862b375428afa9e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 12:43:55 +0300 Subject: [PATCH 053/119] Use `LastOrDefault` instead --- osu.Game/Skinning/RulesetSkinProvidingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index 26646d87fe..19efc66814 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -88,7 +88,7 @@ namespace osu.Game.Skinning } } - int lastDefaultSkinIndex = SkinSources.IndexOf(SkinSources.OfType().Last()); + int lastDefaultSkinIndex = SkinSources.IndexOf(SkinSources.OfType().LastOrDefault()); // Ruleset resources should be given the ability to override game-wide defaults // This is achieved by placing them before the last instance of DefaultSkin. From ab977d91f0458c406c3b44db1fe21c664d3c4721 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 20:40:22 +0700 Subject: [PATCH 054/119] fix image test not load looks like forgot to change this after `CurrentPath` shenanigan --- .../Online/TestSceneWikiMarkdownContainer.cs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index b6dce2c398..ec43ee2be3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -102,7 +102,7 @@ needs_cleanup: true { AddStep("Add absolute image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; + markdownContainer.CurrentPath = "https://dev.ppy.sh"; markdownContainer.Text = "![intro](/wiki/Interface/img/intro-screen.jpg)"; }); } @@ -112,8 +112,7 @@ needs_cleanup: true { AddStep("Add relative image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; - markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/"; + markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/"; markdownContainer.Text = "![intro](img/intro-screen.jpg)"; }); } @@ -123,8 +122,7 @@ needs_cleanup: true { AddStep("Add paragraph with block image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; - markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/"; + markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/Interface/"; markdownContainer.Text = @"Line before image ![play menu](img/play-menu.jpg ""Main Menu in osu!"") @@ -138,7 +136,7 @@ Line after image"; { AddStep("Add inline image", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; + markdownContainer.CurrentPath = "https://dev.ppy.sh"; markdownContainer.Text = "![osu! mode icon](/wiki/shared/mode/osu.png) osu!"; }); } @@ -148,7 +146,7 @@ Line after image"; { AddStep("Add Table", () => { - markdownContainer.DocumentUrl = "https://dev.ppy.sh"; + markdownContainer.CurrentPath = "https://dev.ppy.sh"; markdownContainer.Text = @" | Image | Name | Effect | | :-: | :-: | :-- | @@ -166,11 +164,6 @@ Line after image"; { public LinkInline Link; - public new string DocumentUrl - { - set => base.DocumentUrl = value; - } - public override MarkdownTextFlowContainer CreateTextFlow() => new TestMarkdownTextFlowContainer { UrlAdded = link => Link = link, From 0e29ae037b8773ce4c88318ca6063998f2979c30 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 20:50:29 +0700 Subject: [PATCH 055/119] add wide image test --- .../Online/TestSceneWikiMarkdownContainer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index ec43ee2be3..69caa2896b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -160,6 +160,20 @@ Line after image"; }); } + [Test] + public void TestWideImageNotExceedContainer() + { + AddStep("Add image", () => + { + markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/osu!_Program_Files/"; + markdownContainer.Text = "![](img/file_structure.jpg \"The file structure of osu!'s installation folder, on Windows and macOS\")"; + }); + AddStep("Change container width", () => + { + markdownContainer.Width = 0.5f; + }); + } + private class TestMarkdownContainer : WikiMarkdownContainer { public LinkInline Link; From 1c074ff0182c90f56b370d37f7511c942bedeaea Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 20:55:40 +0700 Subject: [PATCH 056/119] add `BlockMarkdownImage` change from AutoSize Both to AutoSize Y and RelativeSize X --- .../Wiki/Markdown/WikiMarkdownImageBlock.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 179762103a..fbc0b8ee67 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -32,11 +32,7 @@ namespace osu.Game.Overlays.Wiki.Markdown { Children = new Drawable[] { - new WikiMarkdownImage(linkInline) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, + new BlockMarkdownImage(linkInline), parentTextComponent.CreateSpriteText().With(t => { t.Text = linkInline.Title; @@ -45,5 +41,15 @@ namespace osu.Game.Overlays.Wiki.Markdown }), }; } + + private class BlockMarkdownImage : WikiMarkdownImage + { + public BlockMarkdownImage(LinkInline linkInline) + : base(linkInline) + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + } + } } } From 2b8d41c0452e94cb9577f64771e08e9b18161f0c Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 21:04:56 +0700 Subject: [PATCH 057/119] add `BlockImageContainer` change from AutoSize Both to AutoSize Y and RelativeSize X --- .../Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index fbc0b8ee67..b321cf328e 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -50,6 +50,18 @@ namespace osu.Game.Overlays.Wiki.Markdown AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; } + + protected override ImageContainer CreateImageContainer(string url) => new BlockImageContainer(url); + + private class BlockImageContainer : ImageContainer + { + public BlockImageContainer(string url) + : base(url) + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + } + } } } } From e58f690210037ed9ddcfa3c3651fc3910442f7fa Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 28 Jun 2021 21:09:00 +0700 Subject: [PATCH 058/119] centering image sprite --- osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index b321cf328e..8d2eca9d5d 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; +using osu.Framework.Graphics.Sprites; using osuTK; namespace osu.Game.Overlays.Wiki.Markdown @@ -61,6 +62,12 @@ namespace osu.Game.Overlays.Wiki.Markdown AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; } + + protected override Sprite CreateSpriteImage() => base.CreateSpriteImage().With(s => + { + s.Anchor = Anchor.TopCentre; + s.Origin = Anchor.TopCentre; + }); } } } From 006cc331c8991e28fefae250824249bf3f0d569b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:51:43 +0300 Subject: [PATCH 059/119] Separate `IMutateApproachCircles` to requiring and hiding --- ...teApproachCircles.cs => IHidesApproachCircles.cs} | 4 ++-- .../Mods/IRequiresApproachCircles.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) rename osu.Game.Rulesets.Osu/Mods/{IMutateApproachCircles.cs => IHidesApproachCircles.cs} (57%) create mode 100644 osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs diff --git a/osu.Game.Rulesets.Osu/Mods/IMutateApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs similarity index 57% rename from osu.Game.Rulesets.Osu/Mods/IMutateApproachCircles.cs rename to osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index 60a5825241..07ca93126d 100644 --- a/osu.Game.Rulesets.Osu/Mods/IMutateApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -4,9 +4,9 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Any mod which affects the animation or visibility of approach circles. Should be used for incompatibility purposes. + /// Any mod which completely hides the approach circles. Used for incompatibility with . /// - public interface IMutateApproachCircles + public interface IHidesApproachCircles { } } diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs new file mode 100644 index 0000000000..f2bd836835 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Osu.Mods +{ + /// + /// Any mod which requires the approach circles to be visible. Used for incompatibility with . + /// + public interface IRequiresApproachCircles + { + } +} From 6a67a6736a5c248efbeab3e2b151838069950038 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:52:39 +0300 Subject: [PATCH 060/119] Mark `IRequireApproachCircles` mods as incompatible with `IHidesApproachCircles` --- osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs index 526e29ad53..d832411104 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModApproachDifferent : Mod, IApplicableToDrawableHitObject, IMutateApproachCircles + public class OsuModApproachDifferent : Mod, IApplicableToDrawableHitObject, IRequiresApproachCircles { public override string Name => "Approach Different"; public override string Acronym => "AD"; @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; public override IconUsage? Icon { get; } = FontAwesome.Regular.Circle; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IHidesApproachCircles) }; [SettingSource("Initial size", "Change the initial size of the approach circle, relative to hit circles.", 0)] public BindableFloat Scale { get; } = new BindableFloat(4) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 84263221a7..a05e4dea03 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Osu.Skinning.Default; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModTraceable : ModWithVisibilityAdjustment, IMutateApproachCircles + public class OsuModTraceable : ModWithVisibilityAdjustment, IRequiresApproachCircles { public override string Name => "Traceable"; public override string Acronym => "TC"; @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IHidesApproachCircles) }; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { From baf736026b1e58578ee10f3fb269ade776a3c35e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:54:21 +0300 Subject: [PATCH 061/119] Mark `IHidesApproachCircles` mods as incompatible with `IRequiresApproachCircles` --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 16b38cd0b1..ee591465cd 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -15,12 +15,12 @@ using osu.Game.Rulesets.Osu.Skinning; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModHidden : ModHidden, IMutateApproachCircles + public class OsuModHidden : ModHidden, IHidesApproachCircles { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs index 6dfabed0df..9aafb02fa2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Adjusts the size of hit objects during their fade in animation. /// - public abstract class OsuModObjectScaleTween : ModWithVisibilityAdjustment, IMutateApproachCircles + public abstract class OsuModObjectScaleTween : ModWithVisibilityAdjustment, IHidesApproachCircles { public override ModType Type => ModType.Fun; @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods protected virtual float EndScale => 1; - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index d3ca2973f0..1854c20aef 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModSpinIn : ModWithVisibilityAdjustment, IMutateApproachCircles + public class OsuModSpinIn : ModWithVisibilityAdjustment, IHidesApproachCircles { public override string Name => "Spin In"; public override string Acronym => "SI"; @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(IMutateApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; From 69dac018c7c7b7a62dc3aeb08fa08e4956c39051 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 28 Jun 2021 18:55:24 +0300 Subject: [PATCH 062/119] Make `OsuModSpinIn` as incompatible with other `IHidesApproachCircles` mods Respecting the TODO comment above it, mark `OsuModSpinIn` as incompatible with other `IHidesApproachCircles` mods as well. --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ee591465cd..9c7784a00a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs index 9aafb02fa2..778447e444 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods protected virtual float EndScale => 1; - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn) }; protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 1854c20aef..47a771c2f1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles) }; + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(IHidesApproachCircles) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; From d88d2644918bba27389c2e6ea5308ab965c2f736 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 29 Jun 2021 09:49:45 +0700 Subject: [PATCH 063/119] prevent image sprite exceed its parent width --- .../Wiki/Markdown/WikiMarkdownImageBlock.cs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 8d2eca9d5d..4b0490d034 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -63,11 +63,28 @@ namespace osu.Game.Overlays.Wiki.Markdown RelativeSizeAxes = Axes.X; } - protected override Sprite CreateSpriteImage() => base.CreateSpriteImage().With(s => + protected override Sprite CreateSpriteImage() => new ImageSprite(); + + private class ImageSprite : Sprite { - s.Anchor = Anchor.TopCentre; - s.Origin = Anchor.TopCentre; - }); + public ImageSprite() + { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + } + + protected override void Update() + { + base.Update(); + + if (Width > Parent.DrawWidth) + { + float ratio = Height / Width; + Width = Parent.DrawWidth; + Height = ratio * Width; + } + } + } } } } From a1fe9df378d88cd5edca44331fb867c59f35d94d Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 29 Jun 2021 10:14:51 +0700 Subject: [PATCH 064/119] add test to check sprite image width --- .../Visual/Online/TestSceneWikiMarkdownContainer.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index 69caa2896b..af2e4fc91a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using Markdig.Syntax.Inlines; using NUnit.Framework; using osu.Framework.Allocation; @@ -9,6 +10,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Graphics.Containers.Markdown; using osu.Game.Overlays; using osu.Game.Overlays.Wiki.Markdown; @@ -168,10 +172,19 @@ Line after image"; markdownContainer.CurrentPath = "https://dev.ppy.sh/wiki/osu!_Program_Files/"; markdownContainer.Text = "![](img/file_structure.jpg \"The file structure of osu!'s installation folder, on Windows and macOS\")"; }); + + AddUntilStep("Wait image to load", () => markdownContainer.ChildrenOfType().First().DelayedLoadCompleted); + AddStep("Change container width", () => { markdownContainer.Width = 0.5f; }); + + AddAssert("Image not exceed container width", () => + { + var spriteImage = markdownContainer.ChildrenOfType().First(); + return Precision.DefinitelyBigger(markdownContainer.DrawWidth, spriteImage.DrawWidth); + }); } private class TestMarkdownContainer : WikiMarkdownContainer From a3b1e1d5fc477f54de3e359f96ea4f3ab5a90cda Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 29 Jun 2021 15:18:40 +0900 Subject: [PATCH 065/119] Check for null ruleset in FilterCriteria --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 8e59dc8579..5f135a3e90 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -93,7 +93,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { bool matchingFilter = true; - matchingFilter &= r.Room.Playlist.Count == 0 || r.Room.Playlist.Any(i => i.Ruleset.Value.Equals(criteria.Ruleset)); + matchingFilter &= r.Room.Playlist.Count == 0 || criteria.Ruleset == null || r.Room.Playlist.Any(i => i.Ruleset.Value.Equals(criteria.Ruleset)); if (!string.IsNullOrEmpty(criteria.SearchString)) matchingFilter &= r.FilterTerms.Any(term => term.Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase)); From 06beeee4d8004e6d7608761f3de0ab73a5b9ee07 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 29 Jun 2021 15:39:01 +0900 Subject: [PATCH 066/119] Cleanup match header test --- .../Multiplayer/TestSceneMatchHeader.cs | 66 +++++++++---------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index 3557bd9127..71ba5db481 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -17,43 +17,39 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUp] public new void Setup() => Schedule(() => { - SelectedRoom.Value = new Room(); + SelectedRoom.Value = new Room + { + Name = { Value = "A very awesome room" }, + Host = { Value = new User { Id = 2, Username = "peppy" } }, + Playlist = + { + new PlaylistItem + { + Beatmap = + { + Value = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = "Title", + Artist = "Artist", + AuthorString = "Author", + }, + Version = "Version", + Ruleset = new OsuRuleset().RulesetInfo + } + }, + RequiredMods = + { + new OsuModDoubleTime(), + new OsuModNoFail(), + new OsuModRelax(), + } + } + } + }; Child = new Header(); }); - - [Test] - public void TestBasicRoom() - { - AddStep("set basic room", () => - { - SelectedRoom.Value.Playlist.Add(new PlaylistItem - { - Beatmap = - { - Value = new BeatmapInfo - { - Metadata = new BeatmapMetadata - { - Title = "Title", - Artist = "Artist", - AuthorString = "Author", - }, - Version = "Version", - Ruleset = new OsuRuleset().RulesetInfo - } - }, - RequiredMods = - { - new OsuModDoubleTime(), - new OsuModNoFail(), - new OsuModRelax(), - } - }); - - SelectedRoom.Value.Name.Value = "A very awesome room"; - SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" }; - }); - } } } From 7997d570308d39ea6c3e1c95beba03c59f119976 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 29 Jun 2021 11:25:35 +0300 Subject: [PATCH 067/119] Mention interfaces being "markers" for the time being --- osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs | 2 +- osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index 07ca93126d..fe0abc453d 100644 --- a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Any mod which completely hides the approach circles. Used for incompatibility with . + /// Marker interface for any mod which completely hides the approach circles. Used for incompatibility with . /// public interface IHidesApproachCircles { diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs index f2bd836835..3220ebf378 100644 --- a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Any mod which requires the approach circles to be visible. Used for incompatibility with . + /// Marker interface for any mod which requires the approach circles to be visible. Used for incompatibility with . /// public interface IRequiresApproachCircles { From bfdbe3c3fe534fc3b0060f4253635065f30b074b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 29 Jun 2021 17:29:25 +0900 Subject: [PATCH 068/119] Fix clocks getting added a second time --- .../Multiplayer/Spectate/CatchUpSyncManager.cs | 7 ++++++- .../Spectate/MultiSpectatorScreen.cs | 17 ++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs index 781123f5bb..94278a47b6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -54,7 +55,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate MasterClock = master; } - public void AddPlayerClock(ISpectatorPlayerClock clock) => playerClocks.Add(clock); + public void AddPlayerClock(ISpectatorPlayerClock clock) + { + Debug.Assert(!playerClocks.Contains(clock)); + playerClocks.Add(clock); + } public void RemovePlayerClock(ISpectatorPlayerClock clock) => playerClocks.Remove(clock); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 013e5551cf..e709cba0ee 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -101,7 +101,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate Expanded = { Value = true }, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - }, leaderboardContainer.Add); + }, l => + { + foreach (var instance in instances) + leaderboard.AddClock(instance.UserId, instance.GameplayClock); + + leaderboardContainer.Add(leaderboard); + }); syncManager.ReadyToStart += onReadyToStart; syncManager.MasterState.BindValueChanged(onMasterStateChanged, true); @@ -166,14 +172,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate } protected override void StartGameplay(int userId, GameplayState gameplayState) - { - var instance = instances.Single(i => i.UserId == userId); - - instance.LoadScore(gameplayState.Score); - - syncManager.AddPlayerClock(instance.GameplayClock); - leaderboard.AddClock(instance.UserId, instance.GameplayClock); - } + => instances.Single(i => i.UserId == userId).LoadScore(gameplayState.Score); protected override void EndGameplay(int userId) { From dbe3150f88465c25dbba23c2111e97968e50b26a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 29 Jun 2021 11:37:03 +0300 Subject: [PATCH 069/119] Mention about marker interfaces even more explicitly --- osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs | 6 +++++- osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index fe0abc453d..4a3b187e83 100644 --- a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -4,8 +4,12 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Marker interface for any mod which completely hides the approach circles. Used for incompatibility with . + /// Marker interface for any mod which completely hides the approach circles. + /// Used for incompatibility with . /// + /// + /// Note that this is only a marker interface for incompatibility purposes, it does not change any gameplay behaviour. + /// public interface IHidesApproachCircles { } diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs index 3220ebf378..1458abfe05 100644 --- a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -4,8 +4,12 @@ namespace osu.Game.Rulesets.Osu.Mods { /// - /// Marker interface for any mod which requires the approach circles to be visible. Used for incompatibility with . + /// Marker interface for any mod which requires the approach circles to be visible. + /// Used for incompatibility with . /// + /// + /// Note that this is only a marker interface for incompatibility purposes, it does not change any gameplay behaviour. + /// public interface IRequiresApproachCircles { } From 3a002e357a63caa42578c39c8cf6cf8082c43cb9 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 29 Jun 2021 19:28:21 +0700 Subject: [PATCH 070/119] rename method --- osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 4b0490d034..1a4f6087c7 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.Wiki.Markdown RelativeSizeAxes = Axes.X; } - protected override Sprite CreateSpriteImage() => new ImageSprite(); + protected override Sprite CreateImageSprite() => new ImageSprite(); private class ImageSprite : Sprite { From 6dd3c6fe9307b5d71c850ef8dbe6d1733d2e8643 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 29 Jun 2021 22:45:18 +0900 Subject: [PATCH 071/119] Make MultiSpectatorScreen and tests more resillient to timing --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 12 +++++++++--- .../Multiplayer/Spectate/MultiSpectatorScreen.cs | 16 +++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index a308e854c6..8c63fb8924 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -82,8 +82,8 @@ namespace osu.Game.Tests.Visual.Multiplayer start(new[] { PLAYER_1_ID, PLAYER_2_ID }); loadSpectateScreen(); - sendFrames(PLAYER_1_ID, 20); - sendFrames(PLAYER_2_ID, 10); + sendFrames(PLAYER_1_ID, 40); + sendFrames(PLAYER_2_ID, 20); checkPaused(PLAYER_2_ID, true); checkPausedInstant(PLAYER_1_ID, false); @@ -196,6 +196,7 @@ namespace osu.Game.Tests.Visual.Multiplayer sendFrames(PLAYER_1_ID, 10); sendFrames(PLAYER_2_ID, 20); + checkPaused(PLAYER_1_ID, false); assertMuted(PLAYER_1_ID, false); assertMuted(PLAYER_2_ID, true); @@ -297,7 +298,12 @@ namespace osu.Game.Tests.Visual.Multiplayer => AddUntilStep($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType().First().GameplayClock.IsRunning != state); private void checkPausedInstant(int userId, bool state) - => AddAssert($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType().First().GameplayClock.IsRunning != state); + { + checkPaused(userId, state); + + // Todo: The following should work, but is broken because SpectatorScreen retrieves the WorkingBeatmap via the BeatmapManager, bypassing the test scene clock and running real-time. + // AddAssert($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType().First().GameplayClock.IsRunning != state); + } private void assertMuted(int userId, bool muted) => AddAssert($"{userId} {(muted ? "is" : "is not")} muted", () => getInstance(userId).Mute == muted); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index e709cba0ee..2a2759e0dd 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -43,6 +43,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private PlayerGrid grid; private MultiSpectatorLeaderboard leaderboard; private PlayerArea currentAudioSource; + private bool canStartMasterClock; /// /// Creates a new . @@ -108,17 +109,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate leaderboardContainer.Add(leaderboard); }); - - syncManager.ReadyToStart += onReadyToStart; - syncManager.MasterState.BindValueChanged(onMasterStateChanged, true); } protected override void LoadComplete() { base.LoadComplete(); - masterClockContainer.Stop(); masterClockContainer.Reset(); + masterClockContainer.Stop(); + + syncManager.ReadyToStart += onReadyToStart; + syncManager.MasterState.BindValueChanged(onMasterStateChanged, true); } protected override void Update() @@ -151,6 +152,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate masterClockContainer.Seek(startTime); masterClockContainer.Start(); + + // Although the clock has been started, this flag is set to allow for later synchronisation state changes to also be able to start it. + canStartMasterClock = true; } private void onMasterStateChanged(ValueChangedEvent state) @@ -158,7 +162,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate switch (state.NewValue) { case MasterClockState.Synchronised: - masterClockContainer.Start(); + if (canStartMasterClock) + masterClockContainer.Start(); + break; case MasterClockState.TooFarAhead: From 331b7237ab5f175067a886668d2ef3de34baf664 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 29 Jun 2021 22:53:31 +0900 Subject: [PATCH 072/119] Attempt to fix one more intermittent test failure --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 8c63fb8924..783db49d36 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -197,8 +197,7 @@ namespace osu.Game.Tests.Visual.Multiplayer sendFrames(PLAYER_1_ID, 10); sendFrames(PLAYER_2_ID, 20); checkPaused(PLAYER_1_ID, false); - assertMuted(PLAYER_1_ID, false); - assertMuted(PLAYER_2_ID, true); + assertOneNotMuted(); checkPaused(PLAYER_1_ID, true); assertMuted(PLAYER_1_ID, true); @@ -305,6 +304,8 @@ namespace osu.Game.Tests.Visual.Multiplayer // AddAssert($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType().First().GameplayClock.IsRunning != state); } + private void assertOneNotMuted() => AddAssert("one player not muted", () => spectatorScreen.ChildrenOfType().Count(p => !p.Mute) == 1); + private void assertMuted(int userId, bool muted) => AddAssert($"{userId} {(muted ? "is" : "is not")} muted", () => getInstance(userId).Mute == muted); From 43375774487498cf412be541ce8d17c3169ee6b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Jun 2021 14:31:27 +0900 Subject: [PATCH 073/119] Remove unused private methods --- .../Multiplayer/TestSceneMultiSpectatorScreen.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 873f8ca35b..ea8f7813fd 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -217,8 +217,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded && (!waitForPlayerLoad || spectatorScreen.AllPlayersLoaded)); } - private void start(int userId, int? beatmapId = null) => start(new[] { userId }, beatmapId); - private void start(int[] userIds, int? beatmapId = null) { AddStep("start play", () => @@ -233,16 +231,6 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - private void finish(int userId) - { - AddStep("end play", () => - { - SpectatorClient.EndPlay(userId); - playingUserIds.Remove(userId); - nextFrame.Remove(userId); - }); - } - private void sendFrames(int userId, int count = 10) => sendFrames(new[] { userId }, count); private void sendFrames(int[] userIds, int count = 10) From e3344c33ea27d2269d60e06aaab6933f10763e1b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 30 Jun 2021 09:57:15 +0300 Subject: [PATCH 074/119] Better convey reason of "Spin In" incompatibility with "Hidden" --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 47a771c2f1..7b2a0c6e0f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -21,8 +21,9 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Circles spin in. No approach circles."; public override double ScoreMultiplier => 1; - // todo: this mod should be able to be compatible with hidden with a bit of further implementation. - public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(IHidesApproachCircles) }; + // todo: this mod needs to be incompatible with "hidden" due to forcing the circle to remain opaque, + // further implementation will be required for supporting that. + public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModObjectScaleTween), typeof(OsuModHidden) }; private const int rotate_offset = 360; private const float rotate_starting_width = 2; @@ -49,10 +50,6 @@ namespace osu.Game.Rulesets.Osu.Mods circle.RotateTo(rotate_offset).Then().RotateTo(0, h.TimePreempt, Easing.InOutSine); circle.ScaleTo(new Vector2(rotate_starting_width, 0)).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine); - - // bypass fade in. - if (state == ArmedState.Idle) - circle.FadeIn(); } break; From 57a21dfb1ca75d4024060ccfc054a2132237907d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Jun 2021 16:11:18 +0900 Subject: [PATCH 075/119] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c845d7f276..481ddc118f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f047859dbb..589afb86be 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 304047ad12..a8bf0e4ab2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From 4b56d94a9806b11e9017ed919cf05cf5a8620c08 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 30 Jun 2021 10:26:27 +0300 Subject: [PATCH 076/119] Revert accidentally pushed part of change --- osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 7b2a0c6e0f..56c246953e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -50,6 +50,10 @@ namespace osu.Game.Rulesets.Osu.Mods circle.RotateTo(rotate_offset).Then().RotateTo(0, h.TimePreempt, Easing.InOutSine); circle.ScaleTo(new Vector2(rotate_starting_width, 0)).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine); + + // bypass fade in. + if (state == ArmedState.Idle) + circle.FadeIn(); } break; From e23614556eaefc9a579f7a42e6cf8f5f8f4c2dc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 30 Jun 2021 19:43:34 +0900 Subject: [PATCH 077/119] Fix slider testscene failures --- .../TestSceneSliderSnaking.cs | 102 ++++++++++-------- 1 file changed, 59 insertions(+), 43 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index 1d500dcc14..744291ae09 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -37,11 +37,13 @@ namespace osu.Game.Rulesets.Osu.Tests private readonly BindableBool snakingIn = new BindableBool(); private readonly BindableBool snakingOut = new BindableBool(); + private IBeatmap beatmap; + private const double duration_of_span = 3605; private const double fade_in_modifier = -1200; protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) - => new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + => new ClockBackedTestWorkingBeatmap(this.beatmap = beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); [BackgroundDependencyLoader] private void load(RulesetConfigCache configCache) @@ -51,8 +53,16 @@ namespace osu.Game.Rulesets.Osu.Tests config.BindWith(OsuRulesetSetting.SnakingOutSliders, snakingOut); } + private Slider slider; private DrawableSlider drawableSlider; + [SetUp] + public void Setup() => Schedule(() => + { + slider = null; + drawableSlider = null; + }); + [SetUpSteps] public override void SetUpSteps() { @@ -67,21 +77,19 @@ namespace osu.Game.Rulesets.Osu.Tests base.SetUpSteps(); AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - double startTime = hitObjects[sliderIndex].StartTime; - addSeekStep(startTime); - retrieveDrawableSlider((Slider)hitObjects[sliderIndex]); + retrieveSlider(sliderIndex); setSnaking(true); - ensureSnakingIn(startTime + fade_in_modifier); + addEnsureSnakingInSteps(() => slider.StartTime + fade_in_modifier); for (int i = 0; i < sliderIndex; i++) { // non-final repeats should not snake out - ensureNoSnakingOut(startTime, i); + addEnsureNoSnakingOutStep(() => slider.StartTime, i); } // final repeat should snake out - ensureSnakingOut(startTime, sliderIndex); + addEnsureSnakingOutSteps(() => slider.StartTime, sliderIndex); } [TestCase(0)] @@ -93,17 +101,15 @@ namespace osu.Game.Rulesets.Osu.Tests base.SetUpSteps(); AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - double startTime = hitObjects[sliderIndex].StartTime; - addSeekStep(startTime); - retrieveDrawableSlider((Slider)hitObjects[sliderIndex]); + retrieveSlider(sliderIndex); setSnaking(false); - ensureNoSnakingIn(startTime + fade_in_modifier); + addEnsureNoSnakingInSteps(() => slider.StartTime + fade_in_modifier); for (int i = 0; i <= sliderIndex; i++) { // no snaking out ever, including final repeat - ensureNoSnakingOut(startTime, i); + addEnsureNoSnakingOutStep(() => slider.StartTime, i); } } @@ -116,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Tests // repeat might have a chance to update its position depending on where in the frame its hit, // so some leniency is allowed here instead of checking strict equality - checkPositionChange(16600, sliderRepeat, positionAlmostSame); + addCheckPositionChangeSteps(() => 16600, getSliderRepeat, positionAlmostSame); } [Test] @@ -126,38 +132,46 @@ namespace osu.Game.Rulesets.Osu.Tests setSnaking(true); base.SetUpSteps(); - checkPositionChange(16600, sliderRepeat, positionDecreased); + addCheckPositionChangeSteps(() => 16600, getSliderRepeat, positionDecreased); } - private void retrieveDrawableSlider(Slider slider) => AddUntilStep($"retrieve slider @ {slider.StartTime}", () => - (drawableSlider = (DrawableSlider)Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == slider)) != null); - - private void ensureSnakingIn(double startTime) => checkPositionChange(startTime, sliderEnd, positionIncreased); - private void ensureNoSnakingIn(double startTime) => checkPositionChange(startTime, sliderEnd, positionRemainsSame); - - private void ensureSnakingOut(double startTime, int repeatIndex) + private void retrieveSlider(int index) { - var repeatTime = timeAtRepeat(startTime, repeatIndex); + AddStep("retrieve slider at index", () => slider = (Slider)beatmap.HitObjects[index]); + addSeekStep(() => slider); + retrieveDrawableSlider(() => slider); + } + private void retrieveDrawableSlider(Func getSliderFunc) + { + AddUntilStep("retrieve drawable slider", () => + (drawableSlider = (DrawableSlider)Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == getSliderFunc())) != null); + } + + private void addEnsureSnakingInSteps(Func startTime) => addCheckPositionChangeSteps(startTime, getSliderEnd, positionIncreased); + private void addEnsureNoSnakingInSteps(Func startTime) => addCheckPositionChangeSteps(startTime, getSliderEnd, positionRemainsSame); + + private void addEnsureSnakingOutSteps(Func startTime, int repeatIndex) + { if (repeatIndex % 2 == 0) - checkPositionChange(repeatTime, sliderStart, positionIncreased); + addCheckPositionChangeSteps(timeAtRepeat(startTime, repeatIndex), getSliderStart, positionIncreased); else - checkPositionChange(repeatTime, sliderEnd, positionDecreased); + addCheckPositionChangeSteps(timeAtRepeat(startTime, repeatIndex), getSliderEnd, positionDecreased); } - private void ensureNoSnakingOut(double startTime, int repeatIndex) => - checkPositionChange(timeAtRepeat(startTime, repeatIndex), positionAtRepeat(repeatIndex), positionRemainsSame); + private void addEnsureNoSnakingOutStep(Func startTime, int repeatIndex) + => addCheckPositionChangeSteps(timeAtRepeat(startTime, repeatIndex), positionAtRepeat(repeatIndex), positionRemainsSame); - private double timeAtRepeat(double startTime, int repeatIndex) => startTime + 100 + duration_of_span * repeatIndex; - private Func positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? (Func)sliderStart : sliderEnd; + private Func timeAtRepeat(Func startTime, int repeatIndex) => () => startTime() + 100 + duration_of_span * repeatIndex; + private Func positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? (Func)getSliderStart : getSliderEnd; - private List sliderCurve => ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; - private Vector2 sliderStart() => sliderCurve.First(); - private Vector2 sliderEnd() => sliderCurve.Last(); + private List getSliderCurve() => ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; + private Vector2 getSliderStart() => getSliderCurve().First(); + private Vector2 getSliderEnd() => getSliderCurve().Last(); - private Vector2 sliderRepeat() + private Vector2 getSliderRepeat() { - var drawable = Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == hitObjects[1]); + var drawable = Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == beatmap.HitObjects[1]); var repeat = drawable.ChildrenOfType>().First().Children.First(); return repeat.Position; } @@ -167,7 +181,7 @@ namespace osu.Game.Rulesets.Osu.Tests private bool positionDecreased(Vector2 previous, Vector2 current) => current.X < previous.X && current.Y < previous.Y; private bool positionAlmostSame(Vector2 previous, Vector2 current) => Precision.AlmostEquals(previous, current, 1); - private void checkPositionChange(double startTime, Func positionToCheck, Func positionAssertion) + private void addCheckPositionChangeSteps(Func startTime, Func positionToCheck, Func positionAssertion) { Vector2 previousPosition = Vector2.Zero; @@ -176,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Tests addSeekStep(startTime); AddStep($"save {positionDescription} position", () => previousPosition = positionToCheck.Invoke()); - addSeekStep(startTime + 100); + addSeekStep(() => startTime() + 100); AddAssert($"{positionDescription} {assertionDescription}", () => { var currentPosition = positionToCheck.Invoke(); @@ -193,19 +207,21 @@ namespace osu.Game.Rulesets.Osu.Tests }); } - private void addSeekStep(double time) + private void addSeekStep(Func slider) { - AddStep($"seek to {time}", () => Player.GameplayClockContainer.Seek(time)); - - AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); + AddStep("seek to slider", () => Player.GameplayClockContainer.Seek(slider().StartTime)); + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(slider().StartTime, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); } - protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap + private void addSeekStep(Func time) { - HitObjects = hitObjects - }; + AddStep("seek to time", () => Player.GameplayClockContainer.Seek(time())); + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time(), Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); + } - private readonly List hitObjects = new List + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = createHitObjects() }; + + private List createHitObjects() => new List { new Slider { From b94d88be5078457279ac09df1086950a335ee8b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 30 Jun 2021 19:49:51 +0900 Subject: [PATCH 078/119] Make method static to better define its usage --- osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index 744291ae09..7dafecfced 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = createHitObjects() }; - private List createHitObjects() => new List + private static List createHitObjects() => new List { new Slider { From 2c1f788f2de20f495baf0e2631e54163824a408c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 30 Jun 2021 19:52:25 +0900 Subject: [PATCH 079/119] Merge methods --- osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index 7dafecfced..3252e6d912 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -139,13 +139,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("retrieve slider at index", () => slider = (Slider)beatmap.HitObjects[index]); addSeekStep(() => slider); - retrieveDrawableSlider(() => slider); - } - - private void retrieveDrawableSlider(Func getSliderFunc) - { AddUntilStep("retrieve drawable slider", () => - (drawableSlider = (DrawableSlider)Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == getSliderFunc())) != null); + (drawableSlider = (DrawableSlider)Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == slider)) != null); } private void addEnsureSnakingInSteps(Func startTime) => addCheckPositionChangeSteps(startTime, getSliderEnd, positionIncreased); From aa7405afa1f8c467c0534cd20101e7e00fa752ab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 30 Jun 2021 20:16:57 +0900 Subject: [PATCH 080/119] Increase number of sent frames to prevent timing issues --- .../Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 5112029873..b8db4067fb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -168,7 +168,7 @@ namespace osu.Game.Tests.Visual.Multiplayer // Send initial frames for both players. A few more for player 1. sendFrames(PLAYER_1_ID, 1000); - sendFrames(PLAYER_2_ID, 10); + sendFrames(PLAYER_2_ID, 30); checkPausedInstant(PLAYER_1_ID, false); checkPausedInstant(PLAYER_2_ID, false); From 4a54e7cdb83db4eb7f86d9af3f2e077d7668088f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Jun 2021 18:30:12 +0900 Subject: [PATCH 081/119] Add tests covering score preparation flow --- .../TestScenePlayerScorePreparation.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs new file mode 100644 index 0000000000..8ea5f3f9ee --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading.Tasks; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Rulesets; +using osu.Game.Scoring; +using osu.Game.Screens.Ranking; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestScenePlayerScorePreparation : OsuPlayerTestScene + { + protected override bool AllowFail => false; + + protected new PreparingPlayer Player => (PreparingPlayer)base.Player; + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + // Ensure track has actually running before attempting to seek + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + } + + [Test] + public void TestPreparationOnResults() + { + AddUntilStep("wait for preparation", () => Player.PreparationCompleted); + } + + [Test] + public void TestPreparationOnExit() + { + AddStep("exit", () => Player.Exit()); + AddUntilStep("wait for preparation", () => Player.PreparationCompleted); + } + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PreparingPlayer(); + + public class PreparingPlayer : TestPlayer + { + public bool PreparationCompleted { get; private set; } + + public bool ResultsCreated { get; private set; } + + public PreparingPlayer() + : base(true, true) + { + } + + protected override ResultsScreen CreateResults(ScoreInfo score) + { + var results = base.CreateResults(score); + ResultsCreated = true; + return results; + } + + protected override Task PrepareScoreForResultsAsync(Score score) + { + PreparationCompleted = true; + return base.PrepareScoreForResultsAsync(score); + } + } + } +} From 00d3baef1191f67dc062ee5205804372e1bf4ca5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Jun 2021 20:23:48 +0900 Subject: [PATCH 082/119] Exit handling flow --- osu.Game/Screens/Play/SubmittingPlayer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index b843915a7c..2ee116a6a3 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -102,6 +102,11 @@ namespace osu.Game.Screens.Play /// Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true. protected virtual bool HandleTokenRetrievalFailure(Exception exception) => true; + public override bool OnExiting(IScreen next) + { + return base.OnExiting(next); + } + protected override async Task PrepareScoreForResultsAsync(Score score) { await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); From 285c49be7ec8ac465081d91294bada9b83ba97d0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 20:28:27 +0200 Subject: [PATCH 083/119] Localise dashboard overlay header. --- .../Dashboard/DashboardOverlayHeader.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 3314ed957a..ce4ec27225 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard { @@ -13,13 +16,14 @@ namespace osu.Game.Overlays.Dashboard { public DashboardTitle() { - Title = "dashboard"; + Title = HomeStrings.UserTitle; Description = "view your friends and other information"; IconTexture = "Icons/Hexacons/social"; } } } + [LocalisableEnum(typeof(DashboardOverlayTabsEnumLocalisationMapper))] public enum DashboardOverlayTabs { Friends, @@ -27,4 +31,22 @@ namespace osu.Game.Overlays.Dashboard [Description("Currently Playing")] CurrentlyPlaying } + + public class DashboardOverlayTabsEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(DashboardOverlayTabs value) + { + switch (value) + { + case DashboardOverlayTabs.Friends: + return FriendsStrings.TitleCompact; + + case DashboardOverlayTabs.CurrentlyPlaying: + return @"Currently Playing"; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } From f2287ba0224badf454d491370d3ad49a894eeecf Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 21:16:21 +0200 Subject: [PATCH 084/119] Localise friends online status stream control. --- .../Changelog/ChangelogUpdateStreamItem.cs | 7 ++--- .../Friends/FriendsOnlineStatusItem.cs | 6 +++-- .../Dashboard/Friends/OnlineStatus.cs | 26 +++++++++++++++++++ osu.Game/Overlays/OverlayStreamItem.cs | 7 ++--- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs index f8e1ac0c84..cb144defbf 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using Humanizer; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Online.API.Requests.Responses; using osuTK.Graphics; @@ -17,11 +18,11 @@ namespace osu.Game.Overlays.Changelog Width *= 2; } - protected override string MainText => Value.DisplayName; + protected override LocalisableString MainText => Value.DisplayName; - protected override string AdditionalText => Value.LatestBuild.DisplayVersion; + protected override LocalisableString AdditionalText => Value.LatestBuild.DisplayVersion; - protected override string InfoText => Value.LatestBuild.Users > 0 ? $"{"user".ToQuantity(Value.LatestBuild.Users, "N0")} online" : null; + protected override LocalisableString InfoText => Value.LatestBuild.Users > 0 ? $"{"user".ToQuantity(Value.LatestBuild.Users, "N0")} online" : null; protected override Color4 GetBarColour(OsuColour colours) => Value.Colour; } diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs index 7e902203f8..11dcb93e6f 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Extensions; +using osu.Framework.Localisation; using osu.Game.Graphics; using osuTK.Graphics; @@ -14,9 +16,9 @@ namespace osu.Game.Overlays.Dashboard.Friends { } - protected override string MainText => Value.Status.ToString(); + protected override LocalisableString MainText => Value.Status.GetLocalisableDescription(); - protected override string AdditionalText => Value.Count.ToString(); + protected override LocalisableString AdditionalText => Value.Count.ToString(); protected override Color4 GetBarColour(OsuColour colours) { diff --git a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs index 6f2f55a6ed..4b5a7ef066 100644 --- a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs +++ b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs @@ -1,12 +1,38 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + namespace osu.Game.Overlays.Dashboard.Friends { + [LocalisableEnum(typeof(OnlineStatusEnumLocalisationMapper))] public enum OnlineStatus { All, Online, Offline } + + public class OnlineStatusEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(OnlineStatus value) + { + switch (value) + { + case OnlineStatus.All: + return SortStrings.All; + + case OnlineStatus.Online: + return UsersStrings.StatusOnline; + + case OnlineStatus.Offline: + return UsersStrings.StatusOffline; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } diff --git a/osu.Game/Overlays/OverlayStreamItem.cs b/osu.Game/Overlays/OverlayStreamItem.cs index cd1391a3d8..56502ff70f 100644 --- a/osu.Game/Overlays/OverlayStreamItem.cs +++ b/osu.Game/Overlays/OverlayStreamItem.cs @@ -12,6 +12,7 @@ using osu.Framework.Allocation; using osu.Game.Graphics.Sprites; using osu.Game.Graphics; using osuTK.Graphics; +using osu.Framework.Localisation; namespace osu.Game.Overlays { @@ -88,11 +89,11 @@ namespace osu.Game.Overlays SelectedItem.BindValueChanged(_ => updateState(), true); } - protected abstract string MainText { get; } + protected abstract LocalisableString MainText { get; } - protected abstract string AdditionalText { get; } + protected abstract LocalisableString AdditionalText { get; } - protected virtual string InfoText => string.Empty; + protected virtual LocalisableString InfoText => string.Empty; protected abstract Color4 GetBarColour(OsuColour colours); From 8da6ecf6a9dd40ee211d349dd9dba6f64e1a6501 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 21:28:07 +0200 Subject: [PATCH 085/119] Localise OverlayPanelDisplayStyle tab control. --- .../Dashboard/Friends/UserSortTabControl.cs | 25 +++++++++++++++++ .../OverlayPanelDisplayStyleControl.cs | 27 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs index 3a5f65212d..dc756e2957 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Dashboard.Friends { @@ -9,6 +12,7 @@ namespace osu.Game.Overlays.Dashboard.Friends { } + [LocalisableEnum(typeof(UserSortCriteriaEnumLocalisationMappper))] public enum UserSortCriteria { [Description(@"Recently Active")] @@ -16,4 +20,25 @@ namespace osu.Game.Overlays.Dashboard.Friends Rank, Username } + + public class UserSortCriteriaEnumLocalisationMappper : EnumLocalisationMapper + { + public override LocalisableString Map(UserSortCriteria value) + { + switch (value) + { + case UserSortCriteria.LastVisit: + return SortStrings.LastVisit; + + case UserSortCriteria.Rank: + return SortStrings.Rank; + + case UserSortCriteria.Username: + return SortStrings.Username; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } diff --git a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs index 0ece96b56c..c2268ff43c 100644 --- a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs +++ b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs @@ -12,6 +12,9 @@ using osu.Framework.Allocation; using osuTK.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; +using System; +using osu.Game.Resources.Localisation.Web; +using osu.Framework.Extensions; namespace osu.Game.Overlays { @@ -57,7 +60,7 @@ namespace osu.Game.Overlays [Resolved] private OverlayColourProvider colourProvider { get; set; } - public LocalisableString TooltipText => $@"{Value} view"; + public LocalisableString TooltipText => Value.GetLocalisableDescription(); private readonly SpriteIcon icon; @@ -98,10 +101,32 @@ namespace osu.Game.Overlays } } + [LocalisableEnum(typeof(OverlayPanelDisplayStyleEnumLocalisationMapper))] public enum OverlayPanelDisplayStyle { Card, List, Brick } + + public class OverlayPanelDisplayStyleEnumLocalisationMapper : EnumLocalisationMapper + { + public override LocalisableString Map(OverlayPanelDisplayStyle value) + { + switch (value) + { + case OverlayPanelDisplayStyle.Card: + return UsersStrings.ViewModeCard; + + case OverlayPanelDisplayStyle.List: + return UsersStrings.ViewModeList; + + case OverlayPanelDisplayStyle.Brick: + return UsersStrings.ViewModeBrick; + + default: + throw new ArgumentOutOfRangeException(nameof(value), value, null); + } + } + } } From 939b2baafecde49976175bd30f977618ef52c1e5 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 30 Jun 2021 22:19:04 +0200 Subject: [PATCH 086/119] Localise overlay "Scroll to top" button. --- osu.Game/Overlays/OverlayScrollContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index c5b4cc3645..ca5fc90027 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -118,7 +119,7 @@ namespace osu.Game.Overlays } }); - TooltipText = "Scroll to top"; + TooltipText = CommonStrings.ButtonsBackToTop; } [BackgroundDependencyLoader] From 583242d96d343bb342f524e3bc0275d111d945af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Jun 2021 13:05:26 +0200 Subject: [PATCH 087/119] Add osu!-styled colour picker control --- .../UserInterface/TestSceneColourPicker.cs | 82 +++++++++++++ .../UserInterfaceV2/OsuColourPicker.cs | 19 +++ .../UserInterfaceV2/OsuHSVColourPicker.cs | 109 ++++++++++++++++++ .../UserInterfaceV2/OsuHexColourPicker.cs | 57 +++++++++ 4 files changed, 267 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs create mode 100644 osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs create mode 100644 osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs create mode 100644 osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs new file mode 100644 index 0000000000..634e45e7a9 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs @@ -0,0 +1,82 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneColourPicker : OsuTestScene + { + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create pickers", () => Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension() + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = @"No OverlayColourProvider", + Font = OsuFont.Default.With(size: 40) + }, + new OsuColourPicker + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + } + }, + new ColourProvidingContainer(OverlayColourScheme.Blue) + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = @"With blue OverlayColourProvider", + Font = OsuFont.Default.With(size: 40) + }, + new OsuColourPicker + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + } + } + } + } + }); + } + + private class ColourProvidingContainer : Container + { + [Cached] + private OverlayColourProvider provider { get; } + + public ColourProvidingContainer(OverlayColourScheme colourScheme) + { + provider = new OverlayColourProvider(colourScheme); + } + } + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs new file mode 100644 index 0000000000..5394e5d0aa --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class OsuColourPicker : ColourPicker + { + public OsuColourPicker() + { + CornerRadius = 10; + Masking = true; + } + + protected override HSVColourPicker CreateHSVColourPicker() => new OsuHSVColourPicker(); + protected override HexColourPicker CreateHexColourPicker() => new OsuHexColourPicker(); + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs new file mode 100644 index 0000000000..2a399cfaf8 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -0,0 +1,109 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Overlays; +using osuTK; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class OsuHSVColourPicker : HSVColourPicker + { + protected override HueSelector CreateHueSelector() => new OsuHueSelector(); + protected override SaturationValueSelector CreateSaturationValueSelector() => new OsuSaturationValueSelector(); + + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour osuColour) + { + Background.Colour = colourProvider?.Dark5 ?? osuColour.GreySeafoamDark; + + Content.Padding = new MarginPadding(10); + Content.Spacing = new Vector2(0, 10); + } + + private class OsuHueSelector : HueSelector + { + public OsuHueSelector() + { + Margin = new MarginPadding + { + Bottom = 15 + }; + + SliderBar.CornerRadius = SliderBar.Height / 2; + SliderBar.Masking = true; + } + + protected override Drawable CreateSliderNub() => new SliderNub(); + + private class SliderNub : CompositeDrawable + { + public SliderNub() + { + InternalChild = new Triangle + { + Width = 20, + Height = 15, + Anchor = Anchor.BottomCentre, + Origin = Anchor.TopCentre + }; + } + } + } + + private class OsuSaturationValueSelector : SaturationValueSelector + { + public OsuSaturationValueSelector() + { + SelectionArea.CornerRadius = 10; + SelectionArea.Masking = true; + // purposefully use hard non-AA'd masking to avoid edge artifacts. + SelectionArea.MaskingSmoothness = 0; + } + + protected override Marker CreateMarker() => new OsuMarker(); + + private class OsuMarker : Marker + { + private readonly Box previewBox; + + public OsuMarker() + { + AutoSizeAxes = Axes.Both; + + InternalChild = new CircularContainer + { + Size = new Vector2(20), + Masking = true, + BorderColour = Colour4.White, + BorderThickness = 3, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0, 1), + Radius = 3, + Colour = Colour4.Black.Opacity(0.3f) + }, + Child = previewBox = new Box + { + RelativeSizeAxes = Axes.Both + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(colour => previewBox.Colour = colour.NewValue, true); + } + } + } + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs new file mode 100644 index 0000000000..331a1b67c9 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs @@ -0,0 +1,57 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class OsuHexColourPicker : HexColourPicker + { + public OsuHexColourPicker() + { + Padding = new MarginPadding(20); + Spacing = 20; + } + + [BackgroundDependencyLoader(true)] + private void load([CanBeNull] OverlayColourProvider overlayColourProvider, OsuColour osuColour) + { + Background.Colour = overlayColourProvider?.Dark6 ?? osuColour.GreySeafoamDarker; + } + + protected override TextBox CreateHexCodeTextBox() => new OsuTextBox(); + protected override ColourPreview CreateColourPreview() => new OsuColourPreview(); + + private class OsuColourPreview : ColourPreview + { + private readonly Box preview; + + public OsuColourPreview() + { + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = preview = new Box + { + RelativeSizeAxes = Axes.Both + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(colour => preview.Colour = colour.NewValue, true); + } + } + } +} From 30a7b034be65e7c7c83ad85518004cd3372d0583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Jul 2021 00:30:43 +0200 Subject: [PATCH 088/119] Add HSV abbreviation to team-shared collection --- osu.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 62751cebb1..d2c5b1223c 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -308,6 +308,7 @@ GL GLSL HID + HSV HTML HUD ID From 719852435f1bc52381f6e4e6ca03e97b6e05460e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 15:10:19 +0900 Subject: [PATCH 089/119] Fix intermittent `PerformFromScreen` test failures due to incorrect screen sequence These tests were manually pushing the `PlayerLoader` / `Player` instances to `SongSelect`, which bypasses safeties in place which avoid the exact issue that came up in https://github.com/ppy/osu/runs/2951759236 (see `AllowSelection` flag specifically). --- .../Visual/Navigation/TestScenePerformFromScreen.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs index 3cedaf9d45..92152bce18 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs @@ -11,6 +11,7 @@ using osu.Game.Overlays; using osu.Game.Screens; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps.IO; using osuTK.Input; using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation; @@ -57,8 +58,11 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestPerformAtSongSelectFromPlayerLoader() { + AddStep("import beatmap", () => ImportBeatmapTest.LoadQuickOszIntoOsu(Game).Wait()); PushAndConfirm(() => new TestPlaySongSelect()); - PushAndConfirm(() => new PlayerLoader(() => new SoloPlayer())); + + AddStep("Press enter", () => InputManager.Key(Key.Enter)); + AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen is PlayerLoader); AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(TestPlaySongSelect) })); AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is TestPlaySongSelect); @@ -68,8 +72,11 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestPerformAtMenuFromPlayerLoader() { + AddStep("import beatmap", () => ImportBeatmapTest.LoadQuickOszIntoOsu(Game).Wait()); PushAndConfirm(() => new TestPlaySongSelect()); - PushAndConfirm(() => new PlayerLoader(() => new SoloPlayer())); + + AddStep("Press enter", () => InputManager.Key(Key.Enter)); + AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen is PlayerLoader); AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true)); AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is MainMenu); From 5bc970af0d5d26f655391ed43275e9869dbc15c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 16:55:33 +0900 Subject: [PATCH 090/119] Make `TestPlayer` inherit from `SoloPlayer` for more flexibility in testing --- osu.Game/Screens/Play/SoloPlayer.cs | 10 ++++++++++ osu.Game/Tests/Visual/TestPlayer.cs | 23 ++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index d0ef4131dc..0099b4c87c 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -12,6 +12,16 @@ namespace osu.Game.Screens.Play { public class SoloPlayer : SubmittingPlayer { + public SoloPlayer() + : this(null) + { + } + + protected SoloPlayer(PlayerConfiguration configuration = null) + : base(configuration) + { + } + protected override APIRequest CreateTokenRequest() { if (!(Beatmap.Value.BeatmapInfo.OnlineBeatmapID is int beatmapId)) diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 09da4db952..52eb06bdc6 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -1,14 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // 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.Bindables; +using osu.Game.Online.API; +using osu.Game.Online.Rooms; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual @@ -16,7 +20,7 @@ namespace osu.Game.Tests.Visual /// /// A player that exposes many components that would otherwise not be available, for testing purposes. /// - public class TestPlayer : Player + public class TestPlayer : SoloPlayer { protected override bool PauseOnFocusLost { get; } @@ -35,6 +39,9 @@ namespace osu.Game.Tests.Visual public new HealthProcessor HealthProcessor => base.HealthProcessor; + public bool TokenCreationRequested { get; private set; } + public bool SubmissionRequested { get; private set; } + public new bool PauseCooldownActive => base.PauseCooldownActive; public readonly List Results = new List(); @@ -49,6 +56,20 @@ namespace osu.Game.Tests.Visual PauseOnFocusLost = pauseOnFocusLost; } + protected override bool HandleTokenRetrievalFailure(Exception exception) => false; + + protected override APIRequest CreateTokenRequest() + { + TokenCreationRequested = true; + return base.CreateTokenRequest(); + } + + protected override APIRequest CreateSubmissionRequest(Score score, long token) + { + SubmissionRequested = true; + return base.CreateSubmissionRequest(score, token); + } + protected override void PrepareReplay() { // Generally, replay generation is handled by whatever is constructing the player. From 397d2491b3e2b1f74b99bab0549c17ba96a2664d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 16:55:44 +0900 Subject: [PATCH 091/119] Update test scenes to actually cover submission logic --- .../TestScenePlayerScorePreparation.cs | 69 ----------------- .../TestScenePlayerScoreSubmission.cs | 74 +++++++++++++++++++ 2 files changed, 74 insertions(+), 69 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs create mode 100644 osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs deleted file mode 100644 index 8ea5f3f9ee..0000000000 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScorePreparation.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Threading.Tasks; -using NUnit.Framework; -using osu.Framework.Screens; -using osu.Framework.Testing; -using osu.Game.Rulesets; -using osu.Game.Scoring; -using osu.Game.Screens.Ranking; - -namespace osu.Game.Tests.Visual.Gameplay -{ - public class TestScenePlayerScorePreparation : OsuPlayerTestScene - { - protected override bool AllowFail => false; - - protected new PreparingPlayer Player => (PreparingPlayer)base.Player; - - [SetUpSteps] - public override void SetUpSteps() - { - base.SetUpSteps(); - - // Ensure track has actually running before attempting to seek - AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - } - - [Test] - public void TestPreparationOnResults() - { - AddUntilStep("wait for preparation", () => Player.PreparationCompleted); - } - - [Test] - public void TestPreparationOnExit() - { - AddStep("exit", () => Player.Exit()); - AddUntilStep("wait for preparation", () => Player.PreparationCompleted); - } - - protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PreparingPlayer(); - - public class PreparingPlayer : TestPlayer - { - public bool PreparationCompleted { get; private set; } - - public bool ResultsCreated { get; private set; } - - public PreparingPlayer() - : base(true, true) - { - } - - protected override ResultsScreen CreateResults(ScoreInfo score) - { - var results = base.CreateResults(score); - ResultsCreated = true; - return results; - } - - protected override Task PrepareScoreForResultsAsync(Score score) - { - PreparationCompleted = true; - return base.PrepareScoreForResultsAsync(score); - } - } - } -} diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs new file mode 100644 index 0000000000..24f8227148 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Online.API; +using osu.Game.Online.Rooms; +using osu.Game.Online.Solo; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Ranking; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestScenePlayerScoreSubmission : OsuPlayerTestScene + { + protected override bool AllowFail => false; + + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + + protected override TestPlayer CreatePlayer(Ruleset ruleset) + { + SelectedMods.Value = new[] { ruleset.GetAllMods().OfType().First() }; + return new TestPlayer(false); + } + + [SetUpSteps] + public override void SetUpSteps() + { + AddStep("Prepare test API", () => + { + dummyAPI.HandleRequest = request => + { + switch (request) + { + case CreateSoloScoreRequest tokenRequest: + tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); + return true; + } + + return false; + }; + }); + + base.SetUpSteps(); + + // Ensure track has actually running before attempting to seek + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + } + + [Test] + public void TestSubmissionOnResults() + { + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + + AddUntilStep("wait for submission", () => Player.SubmissionRequested); + } + + [Test] + public void TestSubmissionOnExit() + { + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddStep("exit", () => Player.Exit()); + AddUntilStep("wait for submission", () => Player.SubmissionRequested); + } + } +} From 04b874bb009a85b67c5783f30aa4a6f2bfb6862a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:02:33 +0900 Subject: [PATCH 092/119] Add flow for submitting score on exiting `SubmittingPlayer` --- osu.Game/Screens/Play/SubmittingPlayer.cs | 60 ++++++++++++++--------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index 2ee116a6a3..bbb6a21f39 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -27,6 +27,8 @@ namespace osu.Game.Screens.Play [Resolved] private IAPIProvider api { get; set; } + private TaskCompletionSource scoreSubmissionSource; + protected SubmittingPlayer(PlayerConfiguration configuration = null) : base(configuration) { @@ -102,36 +104,18 @@ namespace osu.Game.Screens.Play /// Whether gameplay should be immediately exited as a result. Returning false allows the gameplay session to continue. Defaults to true. protected virtual bool HandleTokenRetrievalFailure(Exception exception) => true; - public override bool OnExiting(IScreen next) - { - return base.OnExiting(next); - } - protected override async Task PrepareScoreForResultsAsync(Score score) { await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); - // token may be null if the request failed but gameplay was still allowed (see HandleTokenRetrievalFailure). - if (token == null) - return; + await submitScore(score).ConfigureAwait(false); + } - var tcs = new TaskCompletionSource(); - var request = CreateSubmissionRequest(score, token.Value); + public override bool OnExiting(IScreen next) + { + submitScore(Score); - request.Success += s => - { - score.ScoreInfo.OnlineScoreID = s.ID; - tcs.SetResult(true); - }; - - request.Failure += e => - { - Logger.Error(e, "Failed to submit score"); - tcs.SetResult(false); - }; - - api.Queue(request); - await tcs.Task.ConfigureAwait(false); + return base.OnExiting(next); } /// @@ -148,5 +132,33 @@ namespace osu.Game.Screens.Play /// The score to be submitted. /// The submission token. protected abstract APIRequest CreateSubmissionRequest(Score score, long token); + + private Task submitScore(Score score) + { + // token may be null if the request failed but gameplay was still allowed (see HandleTokenRetrievalFailure). + if (token == null) + return Task.CompletedTask; + + if (scoreSubmissionSource != null) + return scoreSubmissionSource.Task; + + scoreSubmissionSource = new TaskCompletionSource(); + var request = CreateSubmissionRequest(score, token.Value); + + request.Success += s => + { + score.ScoreInfo.OnlineScoreID = s.ID; + scoreSubmissionSource.SetResult(true); + }; + + request.Failure += e => + { + Logger.Error(e, "Failed to submit score"); + scoreSubmissionSource.SetResult(false); + }; + + api.Queue(request); + return scoreSubmissionSource.Task; + } } } From 6e8d4e382ebf3597181cee171b20ed175dab9fc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:20:40 +0900 Subject: [PATCH 093/119] Add test coverage of token failure scenarios --- .../TestScenePlayerScoreSubmission.cs | 96 +++++++++++++------ 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 24f8227148..4088fc855d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -1,10 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; -using osu.Framework.Testing; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; @@ -21,14 +21,74 @@ namespace osu.Game.Tests.Visual.Gameplay private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + protected override bool HasCustomSteps => true; + protected override TestPlayer CreatePlayer(Ruleset ruleset) { SelectedMods.Value = new[] { ruleset.GetAllMods().OfType().First() }; return new TestPlayer(false); } - [SetUpSteps] - public override void SetUpSteps() + [Test] + public void TestNoSubmissionOnResultsWithNoToken() + { + prepareTokenResponse(false); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + + AddAssert("ensure no submission", () => !Player.SubmissionRequested); + } + + [Test] + public void TestSubmissionOnResults() + { + prepareTokenResponse(true); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + + AddAssert("ensure submission", () => Player.SubmissionRequested); + } + + [Test] + public void TestNoSubmissionOnExitWithNoToken() + { + prepareTokenResponse(false); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddStep("exit", () => Player.Exit()); + + AddAssert("ensure no submission", () => !Player.SubmissionRequested); + } + + [Test] + public void TestSubmissionOnExit() + { + prepareTokenResponse(true); + + CreateTest(() => { }); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddStep("exit", () => Player.Exit()); + AddUntilStep("wait for submission", () => Player.SubmissionRequested); + } + + private void prepareTokenResponse(bool validToken) { AddStep("Prepare test API", () => { @@ -37,38 +97,16 @@ namespace osu.Game.Tests.Visual.Gameplay switch (request) { case CreateSoloScoreRequest tokenRequest: - tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); + if (validToken) + tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); + else + tokenRequest.TriggerFailure(new Exception()); return true; } return false; }; }); - - base.SetUpSteps(); - - // Ensure track has actually running before attempting to seek - AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); - } - - [Test] - public void TestSubmissionOnResults() - { - AddUntilStep("wait for token request", () => Player.TokenCreationRequested); - - AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); - - AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); - - AddUntilStep("wait for submission", () => Player.SubmissionRequested); - } - - [Test] - public void TestSubmissionOnExit() - { - AddUntilStep("wait for token request", () => Player.TokenCreationRequested); - AddStep("exit", () => Player.Exit()); - AddUntilStep("wait for submission", () => Player.SubmissionRequested); } } } From b00ee67895cba2bdbe64c49c9b698f87413bb2fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:25:47 +0900 Subject: [PATCH 094/119] Remove excess whitespace --- osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index ce4ec27225..056d4ad6f7 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Dashboard switch (value) { case DashboardOverlayTabs.Friends: - return FriendsStrings.TitleCompact; + return FriendsStrings.TitleCompact; case DashboardOverlayTabs.CurrentlyPlaying: return @"Currently Playing"; From 74c63e15bef6d50aa8e4a43a44a7f8a449d0984c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:38:28 +0900 Subject: [PATCH 095/119] Mark score failed on fail and exit --- .../TestScenePlayerScoreSubmission.cs | 38 ++++++++++++++----- osu.Game/Screens/Play/Player.cs | 5 +++ osu.Game/Screens/Play/SubmittingPlayer.cs | 4 +- osu.Game/Tests/Visual/TestPlayer.cs | 5 ++- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 4088fc855d..ada50fbcf4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -23,9 +23,14 @@ namespace osu.Game.Tests.Visual.Gameplay protected override bool HasCustomSteps => true; + private bool allowFail; + protected override TestPlayer CreatePlayer(Ruleset ruleset) { - SelectedMods.Value = new[] { ruleset.GetAllMods().OfType().First() }; + SelectedMods.Value = !allowFail + ? new[] { ruleset.GetAllMods().OfType().First() } + : Array.Empty(); + return new TestPlayer(false); } @@ -34,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(false); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); @@ -43,7 +48,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); - AddAssert("ensure no submission", () => !Player.SubmissionRequested); + AddAssert("ensure no submission", () => Player.SubmittedScore == null); } [Test] @@ -51,7 +56,7 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(true); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); @@ -59,8 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); - - AddAssert("ensure submission", () => Player.SubmissionRequested); + AddAssert("ensure passing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == true); } [Test] @@ -68,12 +72,26 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(false); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddStep("exit", () => Player.Exit()); + AddAssert("ensure no submission", () => Player.SubmittedScore == null); + } + + [Test] + public void TestSubmissionOnFail() + { + prepareTokenResponse(true); + + CreateTest(() => allowFail = true); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + AddUntilStep("wait for fail", () => Player.HasFailed); AddStep("exit", () => Player.Exit()); - AddAssert("ensure no submission", () => !Player.SubmissionRequested); + AddAssert("ensure failing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == false); } [Test] @@ -81,11 +99,11 @@ namespace osu.Game.Tests.Visual.Gameplay { prepareTokenResponse(true); - CreateTest(() => { }); + CreateTest(() => allowFail = false); AddUntilStep("wait for token request", () => Player.TokenCreationRequested); AddStep("exit", () => Player.Exit()); - AddUntilStep("wait for submission", () => Player.SubmissionRequested); + AddAssert("ensure failing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == false); } private void prepareTokenResponse(bool validToken) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 58f60d14cf..97854ee12f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -768,6 +768,7 @@ namespace osu.Game.Screens.Play return false; HasFailed = true; + Score.ScoreInfo.Passed = false; // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. @@ -950,6 +951,10 @@ namespace osu.Game.Screens.Play { screenSuspension?.Expire(); + // if arriving here and the results screen preparation task hasn't run, it's safe to say the user has not completed the beatmap. + if (prepareScoreForDisplayTask == null) + Score.ScoreInfo.Passed = false; + // EndPlaying() is typically called from ReplayRecorder.Dispose(). Disposal is currently asynchronous. // To resolve test failures, forcefully end playing synchronously when this screen exits. // Todo: Replace this with a more permanent solution once osu-framework has a synchronous cleanup method. diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index bbb6a21f39..7c5a06707d 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -113,9 +113,11 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { + var exiting = base.OnExiting(next); + submitScore(Score); - return base.OnExiting(next); + return exiting; } /// diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 52eb06bdc6..5e5f20b307 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -40,7 +40,8 @@ namespace osu.Game.Tests.Visual public new HealthProcessor HealthProcessor => base.HealthProcessor; public bool TokenCreationRequested { get; private set; } - public bool SubmissionRequested { get; private set; } + + public Score SubmittedScore { get; private set; } public new bool PauseCooldownActive => base.PauseCooldownActive; @@ -66,7 +67,7 @@ namespace osu.Game.Tests.Visual protected override APIRequest CreateSubmissionRequest(Score score, long token) { - SubmissionRequested = true; + SubmittedScore = score; return base.CreateSubmissionRequest(score, token); } From a6323b7d87fba2a0adad4a750a9155fcde16bf49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 17:54:59 +0900 Subject: [PATCH 096/119] Use `APIException` --- .../Visual/Gameplay/TestScenePlayerScoreSubmission.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index ada50fbcf4..27f9fc85cf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -118,7 +118,7 @@ namespace osu.Game.Tests.Visual.Gameplay if (validToken) tokenRequest.TriggerSuccess(new APIScoreToken { ID = 1234 }); else - tokenRequest.TriggerFailure(new Exception()); + tokenRequest.TriggerFailure(new APIException("something went wrong!", null)); return true; } From 3816c486d5fb5f13c226f8b1cd72f457cef4a51c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jul 2021 19:03:55 +0900 Subject: [PATCH 097/119] Guard against a potential startup crash if user's preferred ruleset has a compatibility issue Resolves this issue seen at https://github.com/ppy/osu/issues/13722#issuecomment-872088071. --- osu.Game/OsuGame.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 32136b8789..14309e2296 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -223,7 +223,20 @@ namespace osu.Game // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); - Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); + + var preferredRuleset = RulesetStore.GetRuleset(configRuleset.Value); + + try + { + Ruleset.Value = preferredRuleset ?? RulesetStore.AvailableRulesets.First(); + } + catch (Exception e) + { + // on startup, a ruleset may be selected which has compatibility issues. + Logger.Error(e, $@"Failed to switch to preferred ruleset {preferredRuleset}."); + Ruleset.Value = RulesetStore.AvailableRulesets.First(); + } + Ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0; // bind config int to database SkinInfo From a78d1b4c2ee283e8e83f9013bc4bacd762bbacea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Jul 2021 19:37:21 +0900 Subject: [PATCH 098/119] Update SR colours to match osu-web --- osu.Game/Graphics/OsuColour.cs | 4 ++-- osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 15967c37c2..a44c28eaa6 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -32,10 +32,10 @@ namespace osu.Game.Graphics return Pink; case DifficultyRating.Expert: - return useLighterColour ? PurpleLight : Purple; + return PurpleLight; case DifficultyRating.ExpertPlus: - return useLighterColour ? Gray9 : Gray0; + return useLighterColour ? Gray9 : Color4Extensions.FromHex("#121415"); } } diff --git a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs index 7aba699216..e59a0de316 100644 --- a/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs @@ -4,9 +4,7 @@ using System.Globalization; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; @@ -111,12 +109,9 @@ namespace osu.Game.Screens.Ranking.Expanded var rating = Current.Value.DifficultyRating; - background.Colour = rating == DifficultyRating.ExpertPlus - ? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959")) - : (ColourInfo)colours.ForDifficultyRating(rating); + background.Colour = colours.ForDifficultyRating(rating, true); textFlow.Clear(); - textFlow.AddText($"{wholePart}", s => { s.Colour = Color4.Black; From 4c95af4b16a961743639de95451104cd604b8de8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 1 Jul 2021 20:35:31 +0900 Subject: [PATCH 099/119] Add star rating range display --- .../TestSceneStarRatingRangeDisplay.cs | 40 ++++++++ .../Components/StarRatingRangeDisplay.cs | 93 +++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs create mode 100644 osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs new file mode 100644 index 0000000000..cdeafdc9a3 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Online.Rooms; +using osu.Game.Screens.OnlinePlay.Components; +using osu.Game.Tests.Visual.OnlinePlay; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneStarRatingRangeDisplay : OnlinePlayTestScene + { + [SetUp] + public new void Setup() => Schedule(() => + { + SelectedRoom.Value = new Room(); + + Child = new StarRatingRangeDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + }); + + [Test] + public void TestRange([Values(0, 2, 3, 4, 6, 7)] double min, [Values(0, 2, 3, 4, 6, 7)] double max) + { + AddStep("set playlist", () => + { + SelectedRoom.Value.Playlist.AddRange(new[] + { + new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarDifficulty = min } } }, + new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarDifficulty = max } } }, + }); + }); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs new file mode 100644 index 0000000000..b2e35d7020 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -0,0 +1,93 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Specialized; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Screens.Ranking.Expanded; +using osuTK; + +namespace osu.Game.Screens.OnlinePlay.Components +{ + public class StarRatingRangeDisplay : OnlinePlayComposite + { + [Resolved] + private OsuColour colours { get; set; } + + private StarRatingDisplay minDisplay; + private Drawable minBackground; + private StarRatingDisplay maxDisplay; + private Drawable maxBackground; + + public StarRatingRangeDisplay() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 1, + Children = new[] + { + minBackground = new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + maxBackground = new Box + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + minDisplay = new StarRatingDisplay(default), + maxDisplay = new StarRatingDisplay(default) + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Playlist.BindCollectionChanged(updateRange, true); + } + + private void updateRange(object sender, NotifyCollectionChangedEventArgs e) + { + var orderedDifficulties = Playlist.Select(p => p.Beatmap.Value).OrderBy(b => b.StarDifficulty).ToArray(); + + StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarDifficulty : 0, 0); + StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarDifficulty : 0, 0); + + minDisplay.Current.Value = minDifficulty; + maxDisplay.Current.Value = maxDifficulty; + + minBackground.Colour = colours.ForDifficultyRating(minDifficulty.DifficultyRating, true); + maxBackground.Colour = colours.ForDifficultyRating(maxDifficulty.DifficultyRating, true); + } + } +} From 8ab9ea992635622ed9e3b043e23ca7934f418ad3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:03 +0000 Subject: [PATCH 100/119] Bump Realm from 10.2.0 to 10.2.1 Bumps [Realm](https://github.com/realm/realm-dotnet) from 10.2.0 to 10.2.1. - [Release notes](https://github.com/realm/realm-dotnet/releases) - [Changelog](https://github.com/realm/realm-dotnet/blob/master/CHANGELOG.md) - [Commits](https://github.com/realm/realm-dotnet/compare/10.2.0...10.2.1) --- updated-dependencies: - dependency-name: Realm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- 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 481ddc118f..2e388b8626 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -56,6 +56,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..24779fc4d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -35,7 +35,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index a8bf0e4ab2..33ea2261ca 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -99,6 +99,6 @@ - + From c976854e2449b8f659cebe2be22e2ec9da0bc45c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:08 +0000 Subject: [PATCH 101/119] Bump Sentry from 3.4.0 to 3.6.0 Bumps [Sentry](https://github.com/getsentry/sentry-dotnet) from 3.4.0 to 3.6.0. - [Release notes](https://github.com/getsentry/sentry-dotnet/releases) - [Changelog](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-dotnet/compare/3.4.0...3.6.0) --- updated-dependencies: - dependency-name: Sentry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..0ab6bb9ba6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -38,7 +38,7 @@ - + From e5e468e38787da508cd291a205e7ce406c34be3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:11 +0000 Subject: [PATCH 102/119] Bump SharpCompress from 0.28.2 to 0.28.3 Bumps [SharpCompress](https://github.com/adamhathcock/sharpcompress) from 0.28.2 to 0.28.3. - [Release notes](https://github.com/adamhathcock/sharpcompress/releases) - [Commits](https://github.com/adamhathcock/sharpcompress/compare/0.28.2...0.28.3) --- updated-dependencies: - dependency-name: SharpCompress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..f857d155ec 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -39,7 +39,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a8bf0e4ab2..f1ee770688 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -94,7 +94,7 @@ - + From 71867337b6c4e00310d3232b3ca88ccaebc9f3d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:15 +0000 Subject: [PATCH 103/119] Bump HtmlAgilityPack from 1.11.33 to 1.11.34 Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.11.33 to 1.11.34. - [Release notes](https://github.com/zzzprojects/html-agility-pack/releases) - [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.11.33...v1.11.34) --- updated-dependencies: - dependency-name: HtmlAgilityPack dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..f5838f5109 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -20,7 +20,7 @@ - + From 0d3de488de65aeb6310d924fadc67e8433b0151c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:17 +0000 Subject: [PATCH 104/119] Bump NUnit3TestAdapter from 3.17.0 to 4.0.0 Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 3.17.0 to 4.0.0. - [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases) - [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V3.17...V4.0.0) --- updated-dependencies: - dependency-name: NUnit3TestAdapter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../osu.Game.Rulesets.EmptyFreeform.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- .../osu.Game.Rulesets.EmptyScrolling.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index 5eb5efa54c..3dd6be7307 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index d7c116411a..0c4bfe0ed7 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index 89b551286b..bb0a487274 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index d7c116411a..0c4bfe0ed7 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 7a74563b2b..da8a0540f4 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -9,7 +9,7 @@ - + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 83d0744588..484da8e22e 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index b2a0912d19..6df555617b 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 1efd19f49d..68be34d153 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 8fb167ba10..532fdc5cb0 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 35d3c7f202..161e248d96 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 2084be765a..ba096abd36 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From b320528eb59b72b50a53bf33e1706f7c6a428525 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:22 +0000 Subject: [PATCH 105/119] Bump Humanizer from 2.10.1 to 2.11.10 Bumps [Humanizer](https://github.com/Humanizr/Humanizer) from 2.10.1 to 2.11.10. - [Release notes](https://github.com/Humanizr/Humanizer/releases) - [Changelog](https://github.com/Humanizr/Humanizer/blob/main/release_notes.md) - [Commits](https://github.com/Humanizr/Humanizer/compare/v2.10.1...v2.11.10) --- updated-dependencies: - dependency-name: Humanizer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..74ed0b8299 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index a8bf0e4ab2..8226d23e0a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -89,7 +89,7 @@ - + From e7c7b8512ac012bb77852603c079893a9471a147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:25 +0000 Subject: [PATCH 106/119] Bump Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson Bumps [Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson](https://github.com/dotnet/aspnetcore) from 5.0.6 to 5.0.7. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.6...v5.0.7) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..2709f25bb4 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -25,7 +25,7 @@ - + From fb2d08b9ee2a18501464c9c3583c71a349e969d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:29 +0000 Subject: [PATCH 107/119] Bump ppy.LocalisationAnalyser from 2021.608.0 to 2021.614.0 Bumps [ppy.LocalisationAnalyser](https://github.com/ppy/osu-localisation-analyser) from 2021.608.0 to 2021.614.0. - [Release notes](https://github.com/ppy/osu-localisation-analyser/releases) - [Commits](https://github.com/ppy/osu-localisation-analyser/compare/2021.608.0...2021.614.0) --- updated-dependencies: - dependency-name: ppy.LocalisationAnalyser dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..b8502216f3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -31,7 +31,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From f6234864cc8cfe11d678d2a4ed3226003ff06ff9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:33 +0000 Subject: [PATCH 108/119] Bump Microsoft.AspNetCore.SignalR.Client from 5.0.6 to 5.0.7 Bumps [Microsoft.AspNetCore.SignalR.Client](https://github.com/dotnet/aspnetcore) from 5.0.6 to 5.0.7. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.6...v5.0.7) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.SignalR.Client dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..44e7a00839 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + From d0ae946cb6d70a81e4b4b453db31fc480fa16f2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jul 2021 17:02:38 +0000 Subject: [PATCH 109/119] Bump Microsoft.AspNetCore.SignalR.Protocols.MessagePack Bumps [Microsoft.AspNetCore.SignalR.Protocols.MessagePack](https://github.com/dotnet/aspnetcore) from 5.0.6 to 5.0.7. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Commits](https://github.com/dotnet/aspnetcore/compare/v5.0.6...v5.0.7) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.MessagePack dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 589afb86be..470f7f48d9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + From 9b0fa6d3fcb66536b1b2b8fe62c54aa005cc773f Mon Sep 17 00:00:00 2001 From: aitani9 <55509723+aitani9@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:38:38 -0700 Subject: [PATCH 110/119] Make flipping reflect across the axes of the selection box --- osu.Game/Skinning/Editor/SkinSelectionHandler.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 23f36ffe5b..7a35c8600d 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -127,6 +127,7 @@ namespace osu.Game.Skinning.Editor public override bool HandleFlip(Direction direction) { var selectionQuad = getSelectionQuad(); + Vector2 scaleFactor = direction == Direction.Horizontal ? new Vector2(-1, 1) : new Vector2(1, -1); foreach (var b in SelectedBlueprints) { @@ -136,10 +137,8 @@ namespace osu.Game.Skinning.Editor updateDrawablePosition(drawableItem, flippedPosition); - drawableItem.Scale *= new Vector2( - direction == Direction.Horizontal ? -1 : 1, - direction == Direction.Vertical ? -1 : 1 - ); + drawableItem.Scale *= scaleFactor; + drawableItem.Rotation -= drawableItem.Rotation % 180 * 2; } return true; From 083e463afd8065f19d082e9e158ab6ad31afdae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 2 Jul 2021 01:02:36 +0200 Subject: [PATCH 111/119] Use alternative hue slider nub design --- .../UserInterfaceV2/OsuHSVColourPicker.cs | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index 2a399cfaf8..06056f239b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -15,6 +16,10 @@ namespace osu.Game.Graphics.UserInterfaceV2 { public class OsuHSVColourPicker : HSVColourPicker { + private const float spacing = 10; + private const float corner_radius = 10; + private const float control_border_thickness = 3; + protected override HueSelector CreateHueSelector() => new OsuHueSelector(); protected override SaturationValueSelector CreateSaturationValueSelector() => new OsuSaturationValueSelector(); @@ -23,37 +28,58 @@ namespace osu.Game.Graphics.UserInterfaceV2 { Background.Colour = colourProvider?.Dark5 ?? osuColour.GreySeafoamDark; - Content.Padding = new MarginPadding(10); - Content.Spacing = new Vector2(0, 10); + Content.Padding = new MarginPadding(spacing); + Content.Spacing = new Vector2(0, spacing); } + private static EdgeEffectParameters createShadowParameters() => new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0, 1), + Radius = 3, + Colour = Colour4.Black.Opacity(0.3f) + }; + private class OsuHueSelector : HueSelector { public OsuHueSelector() { - Margin = new MarginPadding - { - Bottom = 15 - }; - - SliderBar.CornerRadius = SliderBar.Height / 2; + SliderBar.CornerRadius = corner_radius; SliderBar.Masking = true; } - protected override Drawable CreateSliderNub() => new SliderNub(); + protected override Drawable CreateSliderNub() => new SliderNub(this); private class SliderNub : CompositeDrawable { - public SliderNub() + private readonly Bindable hue; + private readonly Box fill; + + public SliderNub(OsuHueSelector osuHueSelector) { - InternalChild = new Triangle + hue = osuHueSelector.Hue.GetBoundCopy(); + + InternalChild = new CircularContainer { - Width = 20, - Height = 15, - Anchor = Anchor.BottomCentre, - Origin = Anchor.TopCentre + Height = 35, + Width = 10, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Masking = true, + BorderColour = Colour4.White, + BorderThickness = control_border_thickness, + EdgeEffect = createShadowParameters(), + Child = fill = new Box + { + RelativeSizeAxes = Axes.Both + } }; } + + protected override void LoadComplete() + { + hue.BindValueChanged(h => fill.Colour = Colour4.FromHSV(h.NewValue, 1, 1), true); + } } } @@ -61,7 +87,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { public OsuSaturationValueSelector() { - SelectionArea.CornerRadius = 10; + SelectionArea.CornerRadius = corner_radius; SelectionArea.Masking = true; // purposefully use hard non-AA'd masking to avoid edge artifacts. SelectionArea.MaskingSmoothness = 0; @@ -82,14 +108,8 @@ namespace osu.Game.Graphics.UserInterfaceV2 Size = new Vector2(20), Masking = true, BorderColour = Colour4.White, - BorderThickness = 3, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Offset = new Vector2(0, 1), - Radius = 3, - Colour = Colour4.Black.Opacity(0.3f) - }, + BorderThickness = control_border_thickness, + EdgeEffect = createShadowParameters(), Child = previewBox = new Box { RelativeSizeAxes = Axes.Both From 0396a03bbc7f9e041a7d0feb10aa906b2f614355 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 12:50:53 +0900 Subject: [PATCH 112/119] Rename `Mod.Ranked` back to avoid breaking ruleset API --- osu.Game/Rulesets/Mods/Mod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 79d16013e3..40c3761768 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Mods public virtual bool UserPlayable => true; [Obsolete("Going forward, the concept of \"ranked\" doesn't exist. The only exceptions are automation mods, which should now override and set UserPlayable to true.")] // Can be removed 20211009 - public virtual bool IsRanked => false; + public virtual bool Ranked => false; /// /// Whether this mod requires configuration to apply changes to the game. From 30467191b2137534aa3aaacb4973938bf20104be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 14:21:48 +0900 Subject: [PATCH 113/119] Remove local handling of `NoFail` addition --- .../Gameplay/TestScenePlayerScoreSubmission.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 27f9fc85cf..d80fbfe309 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using NUnit.Framework; using osu.Framework.Screens; @@ -9,7 +8,6 @@ using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Ranking; @@ -17,22 +15,15 @@ namespace osu.Game.Tests.Visual.Gameplay { public class TestScenePlayerScoreSubmission : OsuPlayerTestScene { - protected override bool AllowFail => false; + protected override bool AllowFail => allowFail; + + private bool allowFail; private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; protected override bool HasCustomSteps => true; - private bool allowFail; - - protected override TestPlayer CreatePlayer(Ruleset ruleset) - { - SelectedMods.Value = !allowFail - ? new[] { ruleset.GetAllMods().OfType().First() } - : Array.Empty(); - - return new TestPlayer(false); - } + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false); [Test] public void TestNoSubmissionOnResultsWithNoToken() From f689e788c9d363136dfc0900acd179a801754b6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 14:24:27 +0900 Subject: [PATCH 114/119] Avoid using game-wide beatmap during score submission --- osu.Game/Screens/Play/SoloPlayer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index 0099b4c87c..ef1087dd62 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -37,9 +37,11 @@ namespace osu.Game.Screens.Play protected override APIRequest CreateSubmissionRequest(Score score, long token) { - Debug.Assert(Beatmap.Value.BeatmapInfo.OnlineBeatmapID != null); + var beatmap = score.ScoreInfo.Beatmap; - int beatmapId = Beatmap.Value.BeatmapInfo.OnlineBeatmapID.Value; + Debug.Assert(beatmap.OnlineBeatmapID != null); + + int beatmapId = beatmap.OnlineBeatmapID.Value; return new SubmitSoloScoreRequest(beatmapId, token, score.ScoreInfo); } From f2d9d78455d2de5495c522cde54b6209dcbbd446 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 14:43:48 +0900 Subject: [PATCH 115/119] Fix some incorrectly invoked `async` calls --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 4 ++-- .../Multiplayer/TestSceneMultiplayerReadyButton.cs | 5 +++-- .../Multiplayer/TestSceneMultiplayerSpectateButton.cs | 9 +++++---- osu.Game/OsuGame.cs | 4 ++++ 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 47cd39dc5a..58d67c11d9 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -116,7 +116,7 @@ namespace osu.Desktop.Updater if (scheduleRecheck) { // check again in 30 minutes. - Scheduler.AddDelayed(async () => await checkForUpdateAsync().ConfigureAwait(false), 60000 * 30); + Scheduler.AddDelayed(() => Task.Run(async () => await checkForUpdateAsync().ConfigureAwait(false)), 60000 * 30); } } @@ -141,7 +141,7 @@ namespace osu.Desktop.Updater Activated = () => { updateManager.PrepareUpdateAsync() - .ContinueWith(_ => updateManager.Schedule(() => game.GracefullyExit())); + .ContinueWith(_ => updateManager.Schedule(() => game?.GracefullyExit())); return true; }; } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index 4f2ca34fb0..fd9aa922b0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -65,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = async () => + OnReadyClick = () => Task.Run(async () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); @@ -77,7 +78,7 @@ namespace osu.Game.Tests.Visual.Multiplayer await Client.ToggleReady(); readyClickOperation.Dispose(); - } + }) }); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index 070158f552..a4b0195b00 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -69,19 +70,19 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnSpectateClick = async () => + OnSpectateClick = () => Task.Run(async () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); await Client.ToggleSpectate(); readyClickOperation.Dispose(); - } + }) }, readyButton = new MultiplayerReadyButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = async () => + OnReadyClick = () => Task.Run(async () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); @@ -93,7 +94,7 @@ namespace osu.Game.Tests.Visual.Multiplayer await Client.ToggleReady(); readyClickOperation.Dispose(); - } + }) } } }; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 14309e2296..dcd2d68b43 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -491,6 +491,10 @@ namespace osu.Game public override Task Import(params ImportTask[] imports) { // encapsulate task as we don't want to begin the import process until in a ready state. + + // ReSharper disable once AsyncVoidLambda + // TODO: This is bad because `new Task` doesn't have a Func override. + // Only used for android imports and a bit of a mess. Probably needs rethinking overall. var importTask = new Task(async () => await base.Import(imports).ConfigureAwait(false)); waitForReady(() => this, _ => importTask.Start()); From 7b0f970e7db162bf356b33b2977f22c638be15db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 16:04:51 +0900 Subject: [PATCH 116/119] Fix ongoing operation being begun in an async context --- .../TestSceneMultiplayerReadyButton.cs | 20 +++++++----- .../TestSceneMultiplayerSpectateButton.cs | 32 ++++++++++++------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index fd9aa922b0..0e036e8868 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -66,19 +66,23 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = () => Task.Run(async () => + OnReadyClick = () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); - if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + Task.Run(async () => { - await Client.StartMatch(); - return; - } + if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + { + await Client.StartMatch(); + return; + } - await Client.ToggleReady(); - readyClickOperation.Dispose(); - }) + await Client.ToggleReady(); + + readyClickOperation.Dispose(); + }); + } }); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index a4b0195b00..4966dfbe50 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -70,31 +70,39 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnSpectateClick = () => Task.Run(async () => + OnSpectateClick = () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); - await Client.ToggleSpectate(); - readyClickOperation.Dispose(); - }) + + Task.Run(async () => + { + await Client.ToggleSpectate(); + readyClickOperation.Dispose(); + }); + } }, readyButton = new MultiplayerReadyButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(200, 50), - OnReadyClick = () => Task.Run(async () => + OnReadyClick = () => { readyClickOperation = OngoingOperationTracker.BeginOperation(); - if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + Task.Run(async () => { - await Client.StartMatch(); - return; - } + if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + { + await Client.StartMatch(); + return; + } - await Client.ToggleReady(); - readyClickOperation.Dispose(); - }) + await Client.ToggleReady(); + + readyClickOperation.Dispose(); + }); + } } } }; From 6a0c5b54c316899168d39f69db1659dc706a0104 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Fri, 2 Jul 2021 15:55:25 +0800 Subject: [PATCH 117/119] Fix obsolete message in `Mod.Ranked` --- osu.Game/Rulesets/Mods/Mod.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 40c3761768..6f00bb6c75 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mods [JsonIgnore] public virtual bool UserPlayable => true; - [Obsolete("Going forward, the concept of \"ranked\" doesn't exist. The only exceptions are automation mods, which should now override and set UserPlayable to true.")] // Can be removed 20211009 + [Obsolete("Going forward, the concept of \"ranked\" doesn't exist. The only exceptions are automation mods, which should now override and set UserPlayable to false.")] // Can be removed 20211009 public virtual bool Ranked => false; /// From d67fc87dcbc27fd0be7a3fd61faf174099fd9e68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 17:24:15 +0900 Subject: [PATCH 118/119] Add some basic testability of external colour setting --- .../Visual/UserInterface/TestSceneColourPicker.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs index 634e45e7a9..fa9179443d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; @@ -14,6 +15,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneColourPicker : OsuTestScene { + private readonly Bindable colour = new Bindable(Colour4.Aquamarine); + [SetUpSteps] public void SetUpSteps() { @@ -42,7 +45,8 @@ namespace osu.Game.Tests.Visual.UserInterface new OsuColourPicker { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + Current = { BindTarget = colour }, } } }, @@ -59,13 +63,18 @@ namespace osu.Game.Tests.Visual.UserInterface new OsuColourPicker { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + Current = { BindTarget = colour }, } } } } } }); + + AddStep("set green", () => colour.Value = Colour4.LimeGreen); + AddStep("set white", () => colour.Value = Colour4.White); + AddStep("set red", () => colour.Value = Colour4.Red); } private class ColourProvidingContainer : Container From 8847915c6a4322d83562e5cb7f2cf65004f33d01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jul 2021 18:51:14 +0900 Subject: [PATCH 119/119] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 2e388b8626..591e00fb27 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c44857a77d..14efcd516e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 4772d700da..0ab0b26430 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - +