From 21f66a19fd21c492f8340cc70ef2934ff1d1033e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Feb 2021 15:55:08 +0900 Subject: [PATCH] Make server authoritative in which mods the client should be using when gameplay starts --- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 8 +++--- .../Multiplayer/MultiplayerMatchSubScreen.cs | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index f3972ab7f9..6d06e638c8 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(_ => UpdateMods()); } public override void OnEntering(IScreen last) @@ -97,7 +97,7 @@ namespace osu.Game.Screens.OnlinePlay.Match { base.OnResuming(last); beginHandlingTrack(); - updateMods(); + 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 5f2f1366f7..3dff291858 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -271,6 +271,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer UserMods.BindValueChanged(onUserModsChanged); client.LoadRequested += onLoadRequested; + client.RoomUpdated += onRoomUpdated; isConnected = client.IsConnected.GetBoundCopy(); isConnected.BindValueChanged(connected => @@ -367,6 +368,27 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } + private void onRoomUpdated() + { + UpdateMods(); // user mods may have changed. + } + + 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 settings mods that the server is not aware of (ie. if the match was started during the selection being changed). + var localUserMods = client.LocalUser.Mods.ToList(); + + Schedule(() => + { + var ruleset = Ruleset.Value.CreateInstance(); + Mods.Value = localUserMods.Select(m => m.ToMod(ruleset)).Concat(SelectedItem.Value.RequiredMods).ToList(); + }); + } + private void onLoadRequested() { Debug.Assert(client.Room != null); @@ -384,7 +406,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.Dispose(isDisposing); if (client != null) + { + client.RoomUpdated -= onRoomUpdated; client.LoadRequested -= onLoadRequested; + } } private class UserModSelectOverlay : LocalPlayerModSelectOverlay