1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-29 06:49:53 +08:00

Adjust logic to properly list selectable mods

This commit is contained in:
Dan Balasescu
2025-04-14 20:23:00 +09:00
Unverified
parent 276e923843
commit 3dcd1a9e74
3 changed files with 37 additions and 18 deletions
@@ -14,6 +14,7 @@ using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Utils;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
@@ -80,7 +81,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
MultiplayerPlaylistItem currentItem = client.Room.CurrentPlaylistItem;
Ruleset ruleset = rulesets.GetRuleset(client.LocalUser.RulesetId ?? currentItem.RulesetID)!.CreateInstance();
Mod[] allowedMods = currentItem.AllowedMods.Select(m => m.ToMod(ruleset)).ToArray();
Mod[] allowedMods = ModUtils.ListUserSelectableFreeMods(client.Room.Settings.MatchType, currentItem.RequiredMods, currentItem.AllowedMods, currentItem.Freestyle, ruleset);
// Update the mod panels to reflect the ones which are valid for selection.
IsValidMod = m => allowedMods.Any(a => a.GetType() == m.GetType());
@@ -551,27 +551,18 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
updateGameplayState();
}
/// <summary>
/// Lists the <see cref="Mod"/>s that are valid to be selected for the user mod style.
/// </summary>
private Mod[] listAllowedMods()
{
if (SelectedItem.Value == null)
return [];
PlaylistItem item = SelectedItem.Value;
RulesetInfo gameplayRuleset = UserRuleset.Value ?? rulesets.GetRuleset(item.RulesetID)!;
Ruleset rulesetInstance = gameplayRuleset.CreateInstance();
return item.AllowedMods.Select(m => m.ToMod(rulesetInstance)).ToArray();
}
/// <summary>
/// Validates the user mod style against the selected item and ruleset style.
/// </summary>
private void validateUserMods()
{
Mod[] allowedMods = listAllowedMods();
if (SelectedItem.Value == null)
return;
PlaylistItem item = SelectedItem.Value;
RulesetInfo gameplayRuleset = UserRuleset.Value ?? rulesets.GetRuleset(item.RulesetID)!;
Mod[] allowedMods = ModUtils.ListUserSelectableFreeMods(MatchType.Playlists, item.RequiredMods, item.AllowedMods, item.Freestyle, gameplayRuleset.CreateInstance());
UserMods.Value = UserMods.Value.Where(m => allowedMods.Any(a => m.GetType() == a.GetType())).ToArray();
}
@@ -588,7 +579,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
IBeatmapInfo gameplayBeatmap = UserBeatmap.Value ?? item.Beatmap;
RulesetInfo gameplayRuleset = UserRuleset.Value ?? rulesets.GetRuleset(item.RulesetID)!;
Ruleset rulesetInstance = gameplayRuleset.CreateInstance();
Mod[] allowedMods = listAllowedMods();
Mod[] allowedMods = ModUtils.ListUserSelectableFreeMods(MatchType.Playlists, item.RequiredMods, item.AllowedMods, item.Freestyle, gameplayRuleset.CreateInstance());
// Update global gameplay state to correspond to the new selection.
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
+27
View File
@@ -320,5 +320,32 @@ namespace osu.Game.Utils
return isRequired ? mod.ValidForMultiplayer : mod.ValidForMultiplayerAsFreeMod;
}
}
/// <summary>
/// Given an online listing of mods and the user's preferred ruleset, gathers the mods which are selectable as free mods by the current user.
/// </summary>
/// <param name="matchType">The type of match being played.</param>
/// <param name="requiredMods">The required mods for the playlist item.</param>
/// <param name="allowedMods">The allowed mods for the playlist item.</param>
/// <param name="freestyle">Whether freestyle is enabled for the playlist item.</param>
/// <param name="userRuleset">The user's preferred ruleset, which may differ from the playlist item's selection on freestyle playlist items.</param>
public static Mod[] ListUserSelectableFreeMods(MatchType matchType, IEnumerable<APIMod> requiredMods, IEnumerable<APIMod> allowedMods, bool freestyle, Ruleset userRuleset)
{
if (freestyle)
{
Mod[] rulesetRequiredMods = requiredMods.Select(m => m.ToMod(userRuleset)).ToArray();
// In freestyle, the playlist item doesn't provide the allowed mods. Instead, all mods are unconditionally allowed by default.
return userRuleset.AllMods.OfType<Mod>()
// But the mods must still be compatible with the room...
.Where(m => IsValidModForMatch(m, matchType, false, true))
// ... And compatible with the required mods listing (this also handles de-duplication).
.Where(m => CheckCompatibleSet(rulesetRequiredMods.Append(m)))
.ToArray();
}
// Without freestyle, only the mods specified by the playlist item are valid.
return allowedMods.Select(m => m.ToMod(userRuleset)).ToArray();
}
}
}