mirror of
https://github.com/ppy/osu.git
synced 2026-05-13 19:54:15 +08:00
Fix non-default mod settings allowing for duplicate freestyle mod selection in multiplayer (#37646)
Fixes a bug that allowed for selecting the same mod twice in multiplayer if the playlist entry has non-default settings for a required mod. This happens due to a strict equality mod check in the mod set compatibility check function, which only considers mods duplicates if their settings are exactly the same. Replacing with a more lenient `Type` check fixes this. Adds a regression test for this behavior Fixes https://github.com/ppy/osu/issues/37625. --------- Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
b8729cb7fd
commit
3f5c113394
@@ -7,8 +7,10 @@ using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Legacy;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.TypeExtensions;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
@@ -33,6 +35,17 @@ namespace osu.Game.Tests.Mods
|
||||
Assert.That(invalid, Is.EquivalentTo(new[] { mod.Object }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestModIsNotCompatibleWithItselfEvenIfSettingsDiffer()
|
||||
{
|
||||
var mod1 = new Mock<CustomMod3>();
|
||||
var mod2 = new Mock<CustomMod3>();
|
||||
mod2.Setup(m => m.Setting).Returns(new BindableBool(true));
|
||||
|
||||
Assert.That(ModUtils.CheckCompatibleSet(new[] { mod1.Object, mod2.Object }, out var invalid), Is.False);
|
||||
Assert.That(invalid, Is.EquivalentTo(new[] { mod2.Object }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestModIsCompatibleByItself()
|
||||
{
|
||||
@@ -397,6 +410,12 @@ namespace osu.Game.Tests.Mods
|
||||
{
|
||||
}
|
||||
|
||||
public abstract class CustomMod3 : Mod, IModCompatibilitySpecification
|
||||
{
|
||||
[SettingSource("Setting")]
|
||||
public virtual BindableBool Setting { get; } = new BindableBool();
|
||||
}
|
||||
|
||||
private class InvalidMultiplayerMod : Mod
|
||||
{
|
||||
public override string Name => string.Empty;
|
||||
|
||||
@@ -330,6 +330,33 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("score multiplier = 1.20", () => this.ChildrenOfType<RankingInformationDisplay>().Single().ModMultiplier.Value, () => Is.EqualTo(1.2).Within(0.01));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestModSelectOverlayNonDefaultSettings()
|
||||
{
|
||||
AddStep("add playlist item", () =>
|
||||
{
|
||||
room.Playlist =
|
||||
[
|
||||
new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||
{
|
||||
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||
RequiredMods =
|
||||
[
|
||||
new APIMod(new OsuModSuddenDeath { FailOnSliderTail = { Value = true } }),
|
||||
],
|
||||
AllowedMods = [],
|
||||
Freestyle = true
|
||||
}
|
||||
];
|
||||
});
|
||||
ClickButtonWhenEnabled<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>();
|
||||
|
||||
AddUntilStep("wait for join", () => RoomJoined);
|
||||
|
||||
ClickButtonWhenEnabled<UserModSelectButton>();
|
||||
AddAssert("sudden death not visible", () => this.ChildrenOfType<MultiplayerUserModSelectOverlay>().Single().ChildrenOfType<ModPanel>().Single(m => m.Mod is ModSuddenDeath).Visible == false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangeSettingsButtonVisibleForHost()
|
||||
{
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace osu.Game.Utils
|
||||
{
|
||||
var m = mods[j];
|
||||
|
||||
if (candidate.Equals(m))
|
||||
if (candidate.GetType() == m.GetType())
|
||||
{
|
||||
invalidMods ??= new List<Mod>();
|
||||
invalidMods.Add(m);
|
||||
|
||||
Reference in New Issue
Block a user