From 89a42d60fbc8f33c6cd28d2baa617b33c57b1312 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 1 Feb 2021 18:50:32 +0900 Subject: [PATCH] General cleanup --- osu.Game.Tests/Mods/ModValidationTest.cs | 14 ++++----- .../TestSceneFreeModSelectOverlay.cs | 5 +-- .../Online/Multiplayer/IMultiplayerClient.cs | 5 +++ .../Multiplayer/IMultiplayerRoomServer.cs | 4 +++ .../Online/Multiplayer/MultiplayerRoomUser.cs | 3 ++ .../Multiplayer/StatefulMultiplayerClient.cs | 6 +++- osu.Game/Overlays/Mods/ModButton.cs | 8 ++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 12 +++++-- .../OnlinePlay/Match/FreeModSelectOverlay.cs | 31 ++----------------- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- .../Multiplayer/MultiplayerMatchSongSelect.cs | 2 +- .../OnlinePlay/OnlinePlaySongSelect.cs | 18 +++++++++-- osu.Game/Screens/Play/HUD/ModDisplay.cs | 3 ++ osu.Game/Screens/Select/MatchSongSelect.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 4 +++ .../Utils/{ModValidation.cs => ModUtils.cs} | 24 +++----------- 16 files changed, 71 insertions(+), 72 deletions(-) rename osu.Game/Utils/{ModValidation.cs => ModUtils.cs} (79%) diff --git a/osu.Game.Tests/Mods/ModValidationTest.cs b/osu.Game.Tests/Mods/ModValidationTest.cs index c7a7e242e9..991adc221e 100644 --- a/osu.Game.Tests/Mods/ModValidationTest.cs +++ b/osu.Game.Tests/Mods/ModValidationTest.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Mods public void TestModIsCompatibleByItself() { var mod = new Mock(); - Assert.That(ModValidation.CheckCompatible(new[] { mod.Object })); + Assert.That(ModUtils.CheckCompatibleSet(new[] { mod.Object })); } [Test] @@ -27,8 +27,8 @@ namespace osu.Game.Tests.Mods mod1.Setup(m => m.IncompatibleMods).Returns(new[] { mod2.Object.GetType() }); // Test both orderings. - Assert.That(ModValidation.CheckCompatible(new[] { mod1.Object, mod2.Object }), Is.False); - Assert.That(ModValidation.CheckCompatible(new[] { mod2.Object, mod1.Object }), Is.False); + Assert.That(ModUtils.CheckCompatibleSet(new[] { mod1.Object, mod2.Object }), Is.False); + Assert.That(ModUtils.CheckCompatibleSet(new[] { mod2.Object, mod1.Object }), Is.False); } [Test] @@ -43,22 +43,22 @@ namespace osu.Game.Tests.Mods var multiMod = new MultiMod(new MultiMod(mod2.Object)); // Test both orderings. - Assert.That(ModValidation.CheckCompatible(new[] { multiMod, mod1.Object }), Is.False); - Assert.That(ModValidation.CheckCompatible(new[] { mod1.Object, multiMod }), Is.False); + Assert.That(ModUtils.CheckCompatibleSet(new[] { multiMod, mod1.Object }), Is.False); + Assert.That(ModUtils.CheckCompatibleSet(new[] { mod1.Object, multiMod }), Is.False); } [Test] public void TestAllowedThroughMostDerivedType() { var mod = new Mock(); - Assert.That(ModValidation.CheckAllowed(new[] { mod.Object }, new[] { mod.Object.GetType() })); + Assert.That(ModUtils.CheckAllowed(new[] { mod.Object }, new[] { mod.Object.GetType() })); } [Test] public void TestNotAllowedThroughBaseType() { var mod = new Mock(); - Assert.That(ModValidation.CheckAllowed(new[] { mod.Object }, new[] { typeof(Mod) }), Is.False); + Assert.That(ModUtils.CheckAllowed(new[] { mod.Object }, new[] { typeof(Mod) }), Is.False); } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index b1700d5b6e..e3342eb6a0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -3,19 +3,16 @@ using NUnit.Framework; using osu.Framework.Graphics.Containers; -using osu.Game.Overlays.Mods; using osu.Game.Screens.OnlinePlay.Match; namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneFreeModSelectOverlay : MultiplayerTestScene { - private ModSelectOverlay overlay; - [SetUp] public new void Setup() => Schedule(() => { - Child = overlay = new FreeModSelectOverlay + Child = new FreeModSelectOverlay { State = { Value = Visibility.Visible } }; diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index f22b0e4e28..6d7b9d24d6 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -57,6 +57,11 @@ namespace osu.Game.Online.Multiplayer /// The new beatmap availability state of the user. Task UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability); + /// + /// Signals that a user in this room changed their local mods. + /// + /// The ID of the user whose mods have changed. + /// The user's new local mods. Task UserModsChanged(int userId, IEnumerable mods); /// diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index 71555ae23d..3527ce6314 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -49,6 +49,10 @@ namespace osu.Game.Online.Multiplayer /// The proposed new beatmap availability state. Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability); + /// + /// Change the local user's mods in the currently joined room. + /// + /// The proposed new mods, excluding any required by the room itself. Task ChangeUserMods(IEnumerable newMods); /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index 4c9643bfce..7de24826dd 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -26,6 +26,9 @@ namespace osu.Game.Online.Multiplayer /// public BeatmapAvailability BeatmapAvailability { get; set; } = BeatmapAvailability.LocallyAvailable(); + /// + /// Any mods applicable only to the local user. + /// [NotNull] public IEnumerable UserMods { get; set; } = Enumerable.Empty(); diff --git a/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs b/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs index a0e903e89a..597bee2764 100644 --- a/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs @@ -232,6 +232,10 @@ namespace osu.Game.Online.Multiplayer public abstract Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability); + /// + /// Change the local user's mods in the currently joined room. + /// + /// The proposed new mods, excluding any required by the room itself. public Task ChangeUserMods(IEnumerable newMods) => ChangeUserMods(newMods.Select(m => new APIMod(m)).ToList()); public abstract Task ChangeUserMods(IEnumerable newMods); @@ -393,7 +397,7 @@ namespace osu.Game.Online.Multiplayer { var user = Room?.Users.SingleOrDefault(u => u.UserID == userId); - // errors here are not critical - user mods is mostly for display. + // errors here are not critical - user mods are mostly for display. if (user == null) return; diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 9ea4f65eb2..ab8efdabcc 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -174,7 +174,7 @@ namespace osu.Game.Overlays.Mods switch (e.Button) { case MouseButton.Right: - OnRightClick(e); + SelectNext(-1); break; } } @@ -183,12 +183,8 @@ namespace osu.Game.Overlays.Mods protected override bool OnClick(ClickEvent e) { SelectNext(1); - return true; - } - protected virtual void OnRightClick(MouseUpEvent e) - { - SelectNext(-1); + return true; } /// diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 2e69f15ff5..2950dc7489 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.Mods private Func isValidMod = m => true; /// - /// A function that checks whether a given mod is valid. + /// A function that checks whether a given mod is selectable. /// [NotNull] public Func IsValidMod @@ -442,12 +442,20 @@ namespace osu.Game.Overlays.Mods IEnumerable modEnumeration = availableMods.Value[section.ModType]; if (!Stacked) - modEnumeration = ModValidation.FlattenMods(modEnumeration); + modEnumeration = ModUtils.FlattenMods(modEnumeration); section.Mods = modEnumeration.Select(validModOrNull).Where(m => m != null); } } + /// + /// Returns a valid form of a given if possible, or null otherwise. + /// + /// + /// This is a recursive process during which any invalid mods are culled while preserving structures where possible. + /// + /// The to check. + /// A valid form of if exists, or null otherwise. [CanBeNull] private Mod validModOrNull([NotNull] Mod mod) { diff --git a/osu.Game/Screens/OnlinePlay/Match/FreeModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/FreeModSelectOverlay.cs index 0d62cc3d37..3cdf25fad0 100644 --- a/osu.Game/Screens/OnlinePlay/Match/FreeModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/FreeModSelectOverlay.cs @@ -5,13 +5,15 @@ using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.OnlinePlay.Match { + /// + /// A used for free-mod selection in online play. + /// public class FreeModSelectOverlay : ModSelectOverlay { protected override bool AllowCustomisation => false; @@ -29,8 +31,6 @@ namespace osu.Game.Screens.OnlinePlay.Match { } - protected override ModButton CreateModButton(Mod mod) => new FreeModButton(mod); - protected override Drawable CreateHeader(string text) => new Container { AutoSizeAxes = Axes.Y, @@ -47,7 +47,6 @@ namespace osu.Game.Screens.OnlinePlay.Match foreach (var button in ButtonsContainer.OfType()) { if (value) - // Note: Buttons where only part of the group has an implementation are not fully supported. button.SelectAt(0); else button.Deselect(); @@ -77,29 +76,5 @@ namespace osu.Game.Screens.OnlinePlay.Match Changed?.Invoke(value); } } - - private class FreeModButton : ModButton - { - public FreeModButton(Mod mod) - : base(mod) - { - } - - protected override bool OnClick(ClickEvent e) - { - onClick(); - return true; - } - - protected override void OnRightClick(MouseUpEvent e) => onClick(); - - private void onClick() - { - if (Selected) - Deselect(); - else - SelectNext(1); - } - } } } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 6367aa54a7..f4136c895f 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -107,7 +107,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (SelectedItem.Value == null) return; - // Remove any extra mods that are no longer allowed. + // Remove any user mods that are no longer allowed. UserMods.Value = UserMods.Value .Where(m => SelectedItem.Value.AllowedMods.Any(a => m.GetType() == a.GetType())) .ToList(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs index e6b7656986..08c00e8372 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Mods.Value = Playlist.FirstOrDefault()?.RequiredMods.Select(m => m.CreateCopy()).ToArray() ?? Array.Empty(); } - protected override void OnSetItem(PlaylistItem item) + protected override void SelectItem(PlaylistItem item) { // If the client is already in a room, update via the client. // Otherwise, update the playlist directly in preparation for it to be submitted to the API on match creation. diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index b75bf93204..46be5591a8 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -76,11 +76,15 @@ namespace osu.Game.Screens.OnlinePlay item.AllowedMods.Clear(); item.AllowedMods.AddRange(freeMods.Value.Select(m => m.CreateCopy())); - OnSetItem(item); + SelectItem(item); return true; } - protected abstract void OnSetItem(PlaylistItem item); + /// + /// Invoked when the user has requested a selection of a beatmap. + /// + /// The resultant . This item has not yet been added to the 's. + protected abstract void SelectItem(PlaylistItem item); public override bool OnBackButton() { @@ -117,8 +121,18 @@ namespace osu.Game.Screens.OnlinePlay return buttons; } + /// + /// Checks whether a given is valid for global selection. + /// + /// The to check. + /// Whether is a valid mod for online play. protected virtual bool IsValidMod(Mod mod) => !(mod is ModAutoplay) && (mod as MultiMod)?.Mods.Any(mm => mm is ModAutoplay) != true; + /// + /// Checks whether a given is valid for per-player free-mod selection. + /// + /// The to check. + /// Whether is a selectable free-mod. protected virtual bool IsValidFreeMod(Mod mod) => IsValidMod(mod); } } diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 2d5b07f056..ce1a8a3205 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -26,6 +26,9 @@ namespace osu.Game.Screens.Play.HUD public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover; + /// + /// Whether the mods should initially appear expanded, before potentially contracting into their final expansion state (depending on ). + /// public bool ExpandOnAppear = true; private readonly Bindable> current = new Bindable>(); diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 23fe9620fe..1de3e0e989 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Select CreateNewItem = createNewItem }; - protected override void OnSetItem(PlaylistItem item) + protected override void SelectItem(PlaylistItem item) { switch (Playlist.Count) { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 4af96b7a29..ed6e0a1028 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -300,6 +300,10 @@ namespace osu.Game.Screens.Select } } + /// + /// Creates the buttons to be displayed in the footer. + /// + /// A set of and an optional which the button opens when pressed. protected virtual IEnumerable<(FooterButton, OverlayContainer)> CreateFooterButtons() => new (FooterButton, OverlayContainer)[] { (new FooterButtonMods { Current = Mods }, ModSelect), diff --git a/osu.Game/Utils/ModValidation.cs b/osu.Game/Utils/ModUtils.cs similarity index 79% rename from osu.Game/Utils/ModValidation.cs rename to osu.Game/Utils/ModUtils.cs index 3597396ec4..808dba2900 100644 --- a/osu.Game/Utils/ModValidation.cs +++ b/osu.Game/Utils/ModUtils.cs @@ -12,9 +12,9 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Utils { /// - /// A set of utilities to validate combinations. + /// A set of utilities to handle combinations. /// - public static class ModValidation + public static class ModUtils { /// /// Checks that all s are compatible with each-other, and that all appear within a set of allowed types. @@ -25,11 +25,11 @@ namespace osu.Game.Utils /// The s to check. /// The set of allowed types. /// Whether all s are compatible with each-other and appear in the set of allowed types. - public static bool CheckCompatibleAndAllowed(IEnumerable combination, IEnumerable allowedTypes) + public static bool CheckCompatibleSetAndAllowed(IEnumerable combination, IEnumerable allowedTypes) { // Prevent multiple-enumeration. var combinationList = combination as ICollection ?? combination.ToArray(); - return CheckCompatible(combinationList) && CheckAllowed(combinationList, allowedTypes); + return CheckCompatibleSet(combinationList) && CheckAllowed(combinationList, allowedTypes); } /// @@ -37,7 +37,7 @@ namespace osu.Game.Utils /// /// The combination to check. /// Whether all s in the combination are compatible with each-other. - public static bool CheckCompatible(IEnumerable combination) + public static bool CheckCompatibleSet(IEnumerable combination) { var incompatibleTypes = new HashSet(); var incomingTypes = new HashSet(); @@ -83,20 +83,6 @@ namespace osu.Game.Utils .All(m => allowedSet.Contains(m.GetType())); } - /// - /// Determines whether a is in a set of incompatible types. - /// - /// - /// A can be incompatible through its most-declared type or any of its base types. - /// - /// The to test. - /// The set of incompatible types. - /// Whether the given is incompatible. - private static bool isModIncompatible(Mod mod, ICollection incompatibleTypes) - => FlattenMod(mod) - .SelectMany(m => m.GetType().EnumerateBaseTypes()) - .Any(incompatibleTypes.Contains); - /// /// Flattens a set of s, returning a new set with all s removed. ///