From 8f04db5df5136f9431e62a6fffce273f2ba8d6bc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 4 May 2022 17:21:19 +0300 Subject: [PATCH] Bring back behaviour of checking incompatibility on gameplay validity --- osu.Game.Tests/Mods/ModUtilsTest.cs | 12 ++++++++++++ osu.Game/OsuGame.cs | 15 +++++---------- osu.Game/Utils/ModUtils.cs | 15 +++++++++++---- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Mods/ModUtilsTest.cs b/osu.Game.Tests/Mods/ModUtilsTest.cs index e858abfe44..4c126f0a3b 100644 --- a/osu.Game.Tests/Mods/ModUtilsTest.cs +++ b/osu.Game.Tests/Mods/ModUtilsTest.cs @@ -134,6 +134,18 @@ namespace osu.Game.Tests.Mods private static readonly object[] invalid_mod_test_scenarios = { + // incompatible pair. + new object[] + { + new Mod[] { new OsuModDoubleTime(), new OsuModHalfTime() }, + new[] { typeof(OsuModDoubleTime), typeof(OsuModHalfTime) } + }, + // incompatible pair with derived class. + new object[] + { + new Mod[] { new OsuModNightcore(), new OsuModHalfTime() }, + new[] { typeof(OsuModNightcore), typeof(OsuModHalfTime) } + }, // system mod. new object[] { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 29985b0893..e9fe8c43de 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -577,16 +577,11 @@ namespace osu.Game if (SelectedMods.Disabled) return; - var validMods = mods.NewValue; - - if (!ModUtils.CheckCompatibleSet(validMods, out var incompatible)) - validMods = validMods.Except(incompatible).ToArray(); - - if (!ModUtils.CheckValidForGameplay(validMods, out var invalid)) - validMods = validMods.Except(invalid).ToArray(); - - // ensure we always have a valid set of mods. - SelectedMods.Value = validMods; + if (!ModUtils.CheckValidForGameplay(mods.NewValue, out var invalid)) + { + // ensure we always have a valid set of mods. + SelectedMods.Value = mods.NewValue.Except(invalid).ToArray(); + } } #endregion diff --git a/osu.Game/Utils/ModUtils.cs b/osu.Game/Utils/ModUtils.cs index e19020a959..c18125054a 100644 --- a/osu.Game/Utils/ModUtils.cs +++ b/osu.Game/Utils/ModUtils.cs @@ -112,7 +112,7 @@ namespace osu.Game.Utils /// Invalid mods, if any were found. Will be null if all mods were valid. /// Whether the input mods were all valid. If false, will contain all invalid entries. public static bool CheckValidForGameplay(IEnumerable mods, [NotNullWhen(false)] out List? invalidMods) - => checkValid(mods, m => m.Type != ModType.System && m.HasImplementation && !(m is MultiMod), out invalidMods); + => checkValid(mods, m => m.Type != ModType.System && m.HasImplementation && !(m is MultiMod), out invalidMods, true); /// /// Checks that all s in a combination are valid as "required mods" in a multiplayer match session. @@ -121,7 +121,7 @@ namespace osu.Game.Utils /// Invalid mods, if any were found. Will be null if all mods were valid. /// Whether the input mods were all valid. If false, will contain all invalid entries. public static bool CheckValidRequiredModsForMultiplayer(IEnumerable mods, [NotNullWhen(false)] out List? invalidMods) - => checkValid(mods, m => m.IsPlayable(ModUsage.MultiplayerGlobal), out invalidMods); + => checkValid(mods, m => m.IsPlayable(ModUsage.MultiplayerGlobal), out invalidMods, true); /// /// Checks that all s in a combination are valid as "free mods" in a multiplayer match session. @@ -130,13 +130,20 @@ namespace osu.Game.Utils /// Invalid mods, if any were found. Will be null if all mods were valid. /// Whether the input mods were all valid. If false, will contain all invalid entries. public static bool CheckValidFreeModsForMultiplayer(IEnumerable mods, [NotNullWhen(false)] out List? invalidMods) - => checkValid(mods, m => m.IsPlayable(ModUsage.MultiplayerLocal), out invalidMods); + => checkValid(mods, m => m.IsPlayable(ModUsage.MultiplayerLocal), out invalidMods, false); - private static bool checkValid(IEnumerable mods, Predicate valid, [NotNullWhen(false)] out List? invalidMods) + private static bool checkValid(IEnumerable mods, Predicate valid, [NotNullWhen(false)] out List? invalidMods, bool checkCompatibility) { mods = mods.ToArray(); invalidMods = null; + if (checkCompatibility) + { + // exclude multi mods from compatibility checks. + // the loop below automatically marks all multi mods as not valid for gameplay anyway. + CheckCompatibleSet(mods.Where(m => !(m is MultiMod)), out invalidMods); + } + foreach (var mod in mods) { if (!valid(mod))