diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 50606aca41..1244ea6e5f 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -166,8 +166,10 @@ public StandAloneChatDisplay(bool postingTextBox = false) Channel.BindValueChanged(channelChanged); } + private readonly Bindable>> availableMods = new Bindable>>(); + [BackgroundDependencyLoader(true)] - private void load(ChannelManager manager, BeatmapModelDownloader beatmaps, BeatmapLookupCache beatmapsCache, OsuConfigManager config) + private void load(ChannelManager manager, BeatmapModelDownloader beatmaps, BeatmapLookupCache beatmapsCache, OsuConfigManager config, OsuGameBase game) { channelManager ??= manager; beatmapsDownloader = beatmaps; @@ -179,6 +181,8 @@ private void load(ChannelManager manager, BeatmapModelDownloader beatmaps, Beatm Scheduler.Add(() => broadcastServer.Add(chatBroadcaster)); Scheduler.Add(processMessageQueue); + + availableMods.BindTo(game.AvailableMods); } protected override void LoadComplete() @@ -459,89 +463,103 @@ private void processChatCommands(string[] parts) break; string[] mods = parts[2].Split("+"); - List modInstances = new List(); + List requiredMods = new List(); + List allowedMods = new List(); - foreach (string mod in mods) + if (mods.Length == 1 && mods[0].Equals(@"fm", StringComparison.OrdinalIgnoreCase)) { - if (mod.Length < 2) - { - Logger.Log($@"[!mp mods] Unknown mod '{mod}', ignoring", LoggingTarget.Runtime, LogLevel.Important); - continue; - } - - string modAcronym = mod[..2]; - var rulesetInstance = RulesetStore.GetRuleset(itemToEdit.RulesetID)?.CreateInstance(); - - if (rulesetInstance == null) - { - Logger.Log($@"[!mp mods] Couldn't create ruleset instance with ruleset ID {itemToEdit.RulesetID}, ignoring mod '{mod}'", - LoggingTarget.Runtime, LogLevel.Important); - continue; - } + // hardcode freemod to allow all mods, leaves requiredMods empty + var newAllowedMods = availableMods.Value + .SelectMany(pair => pair.Value) + .SelectMany(ModUtils.FlattenMod) + .Where(mod => ModUtils.IsValidFreeModForMatchType(mod, Client.Room?.Settings.MatchType ?? MatchType.TeamVersus)); - Mod? modInstance; - - // mod with no params - if (mod.Length == 2) + allowedMods.AddRange(newAllowedMods); + } + else // handle regular mods + { + foreach (string mod in mods) { - modInstance = ParseMod(rulesetInstance, modAcronym, Array.Empty()); - if (modInstance != null) - modInstances.Add(modInstance); - continue; - } + if (mod.Length < 2) + { + Logger.Log($@"[!mp mods] Unknown mod '{mod}', ignoring", LoggingTarget.Runtime, LogLevel.Important); + continue; + } - // mod has parameters - { - JsonNode? modParamsNode; + string modAcronym = mod[..2]; + var rulesetInstance = RulesetStore.GetRuleset(itemToEdit.RulesetID)?.CreateInstance(); - try + if (rulesetInstance == null) { - modParamsNode = JsonNode.Parse(mod[2..]); + Logger.Log($@"[!mp mods] Couldn't create ruleset instance with ruleset ID {itemToEdit.RulesetID}, ignoring mod '{mod}'", + LoggingTarget.Runtime, LogLevel.Important); + continue; } - catch (JsonException) + + Mod? modInstance; + + // mod with no params + if (mod.Length == 2) { - modParamsNode = null; + modInstance = ParseMod(rulesetInstance, modAcronym, Array.Empty()); + if (modInstance != null) + requiredMods.Add(modInstance); + continue; } - if (modParamsNode is JsonArray modParams) + // mod has parameters { - List parsedParamsList = new List(); + JsonNode? modParamsNode; - foreach (JsonNode? node in modParams) + try + { + modParamsNode = JsonNode.Parse(mod[2..]); + } + catch (JsonException) { - if (node?.GetValueKind() is not (JsonValueKind.Number or JsonValueKind.False or JsonValueKind.True)) - continue; + modParamsNode = null; + } - if (node.AsValue().TryGetValue(out int parsedInt)) - { - parsedParamsList.Add(parsedInt); - continue; - } + if (modParamsNode is JsonArray modParams) + { + List parsedParamsList = new List(); - if (node.AsValue().TryGetValue(out double parsedDouble)) + foreach (JsonNode? node in modParams) { - parsedParamsList.Add(parsedDouble); - continue; + if (node?.GetValueKind() is not (JsonValueKind.Number or JsonValueKind.False or JsonValueKind.True)) + continue; + + if (node.AsValue().TryGetValue(out int parsedInt)) + { + parsedParamsList.Add(parsedInt); + continue; + } + + if (node.AsValue().TryGetValue(out double parsedDouble)) + { + parsedParamsList.Add(parsedDouble); + continue; + } + + if (node.AsValue().TryGetValue(out bool parsedBool)) + parsedParamsList.Add(parsedBool); } - if (node.AsValue().TryGetValue(out bool parsedBool)) - parsedParamsList.Add(parsedBool); + modInstance = ParseMod(rulesetInstance, modAcronym, parsedParamsList); + if (modInstance != null) + requiredMods.Add(modInstance); + } + else + { + Logger.Log($@"[!mp mods] Couldn't parse mod parameter(s) '{mod[2..]}', ignoring", LoggingTarget.Runtime, LogLevel.Important); } - - modInstance = ParseMod(rulesetInstance, modAcronym, parsedParamsList); - if (modInstance != null) - modInstances.Add(modInstance); - } - else - { - Logger.Log($@"[!mp mods] Couldn't parse mod parameter(s) '{mod[2..]}', ignoring", LoggingTarget.Runtime, LogLevel.Important); } } } - if (!ModUtils.CheckCompatibleSet(modInstances)) + if (!ModUtils.CheckCompatibleSet(requiredMods)) { - Logger.Log($@"[!mp mods] Mods {string.Join(", ", modInstances.Select(mod => mod.Acronym))} are not compatible together", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log($@"[!mp mods] Mods {string.Join(", ", requiredMods.Select(mod => mod.Acronym))} are not compatible together", LoggingTarget.Runtime, LogLevel.Important); break; } @@ -562,8 +580,8 @@ private void processChatCommands(string[] parts) BeatmapID = beatmapInfo.OnlineID, BeatmapChecksum = beatmapInfo.MD5Hash, RulesetID = itemToEdit.RulesetID, - RequiredMods = modInstances.Select(mod => new APIMod(mod)).ToArray(), - AllowedMods = Array.Empty() + RequiredMods = requiredMods.Select(mod => new APIMod(mod)).ToArray(), + AllowedMods = allowedMods.Select(mod => new APIMod(mod)).ToArray(), }; selectionOperation = operationTracker.BeginOperation();