diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 2946d07588..e755f8c405 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.OnlinePlay.Match managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy(); managerUpdated.BindValueChanged(beatmapUpdated); - UserMods.BindValueChanged(_ => updateMods()); + UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods)); } public override void OnEntering(IScreen last) @@ -97,7 +97,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { base.OnResuming(last); beginHandlingTrack(); - updateMods(); + Scheduler.AddOnce(UpdateMods); } public override bool OnExiting(IScreen next) @@ -128,7 +128,7 @@ namespace osu.Game.Screens.OnlinePlay.Match .Where(m => SelectedItem.Value.AllowedMods.Any(a => m.GetType() == a.GetType())) .ToList(); - updateMods(); + UpdateMods(); Ruleset.Value = SelectedItem.Value.Ruleset.Value; } @@ -145,7 +145,7 @@ namespace osu.Game.Screens.OnlinePlay.Match Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); } - private void updateMods() + protected virtual void UpdateMods() { if (SelectedItem.Value == null) return; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index c5130baa94..3f3fee1b79 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -274,6 +274,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer UserMods.BindValueChanged(onUserModsChanged); client.LoadRequested += onLoadRequested; + client.RoomUpdated += onRoomUpdated; isConnected = client.IsConnected.GetBoundCopy(); isConnected.BindValueChanged(connected => @@ -283,6 +284,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer }, true); } + protected override void UpdateMods() + { + if (SelectedItem.Value == null || client.LocalUser == null) + return; + + // update local mods based on room's reported status for the local user (omitting the base call implementation). + // this makes the server authoritative, and avoids the local user potentially setting mods that the server is not aware of (ie. if the match was started during the selection being changed). + var ruleset = Ruleset.Value.CreateInstance(); + Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); + } + public override bool OnBackButton() { if (client.Room != null && settingsOverlay.State.Value == Visibility.Visible) @@ -391,6 +403,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } + private void onRoomUpdated() + { + // user mods may have changed. + Scheduler.AddOnce(UpdateMods); + } + private void onLoadRequested() { Debug.Assert(client.Room != null); @@ -408,7 +426,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.Dispose(isDisposing); if (client != null) + { + client.RoomUpdated -= onRoomUpdated; client.LoadRequested -= onLoadRequested; + } modSettingChangeTracker?.Dispose(); }