diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index ae117d03d2..bc2d2083fe 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -575,11 +575,16 @@ namespace osu.Game
if (SelectedMods.Disabled)
return;
- if (!ModUtils.CheckValidForGameplay(mods.NewValue, out var invalid))
- {
- // ensure we always have a valid set of mods.
- SelectedMods.Value = mods.NewValue.Except(invalid).ToArray();
- }
+ 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;
}
#endregion
diff --git a/osu.Game/Utils/ModUtils.cs b/osu.Game/Utils/ModUtils.cs
index d5ea74c404..d169ace80a 100644
--- a/osu.Game/Utils/ModUtils.cs
+++ b/osu.Game/Utils/ModUtils.cs
@@ -112,14 +112,34 @@ namespace osu.Game.Utils
/// Invalid mods, if any were found. Can 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);
+
+ ///
+ /// Check the provided combination of mods are valid for a multiplayer match session.
+ ///
+ /// The mods to check.
+ /// Invalid mods, if any were found. Can be null if all mods were valid.
+ /// Whether the input mods were all valid. If false, will contain all invalid entries.
+ public static bool CheckValidForMultiplayer(IEnumerable mods, [NotNullWhen(false)] out List? invalidMods)
+ => checkValid(mods, m => m.PlayableInMultiplayer, out invalidMods);
+
+ ///
+ /// Check the provided combination of mods are valid as "free mods" in a multiplayer match session.
+ ///
+ /// The mods to check.
+ /// Invalid mods, if any were found. Can 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.ValidFreeModInMultiplayer, out invalidMods);
+
+ private static bool checkValid(IEnumerable mods, Predicate valid, [NotNullWhen(false)] out List? invalidMods)
{
mods = mods.ToArray();
-
- CheckCompatibleSet(mods, out invalidMods);
+ invalidMods = null;
foreach (var mod in mods)
{
- if (mod.Type == ModType.System || !mod.HasImplementation || mod is MultiMod)
+ if (!valid(mod))
{
invalidMods ??= new List();
invalidMods.Add(mod);