From ac2a995041590370e31b2b5ef9fb440dcb20d43c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 1 Feb 2021 17:54:56 +0900 Subject: [PATCH] Add user and panel states --- .../TestSceneMultiplayerParticipantsList.cs | 25 ++++++++++++++ .../Online/Multiplayer/IMultiplayerClient.cs | 4 +++ .../Multiplayer/IMultiplayerRoomServer.cs | 4 +++ .../Online/Multiplayer/MultiplayerRoomUser.cs | 7 ++++ .../Multiplayer/StatefulMultiplayerClient.cs | 26 +++++++++++++++ .../Multiplayer/MultiplayerMatchSubScreen.cs | 11 +++++++ .../Participants/ParticipantPanel.cs | 33 ++++++++++++++++++- osu.Game/Screens/Play/HUD/ModDisplay.cs | 14 +++++--- .../Multiplayer/TestMultiplayerClient.cs | 17 ++++++++++ 9 files changed, 136 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index 968a869532..9aa1f2cf99 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -8,6 +8,8 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.OnlinePlay.Multiplayer.Participants; using osu.Game.Users; using osuTK; @@ -123,5 +125,28 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); } + + [Test] + public void TestUserWithMods() + { + AddStep("add user", () => + { + Client.AddUser(new User + { + Id = 0, + Username = $"User 0", + CurrentModeRank = RNG.Next(1, 100000), + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", + }); + + Client.ChangeUserExtraMods(0, new Mod[] + { + new OsuModHardRock(), + new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } } + }); + }); + + AddToggleStep("toggle ready state", v => Client.ChangeUserState(0, v ? MultiplayerUserState.Ready : MultiplayerUserState.Idle)); + } } } diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 19dd473230..37f60ab036 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Threading.Tasks; +using osu.Game.Online.API; using osu.Game.Online.Rooms; namespace osu.Game.Online.Multiplayer @@ -55,6 +57,8 @@ namespace osu.Game.Online.Multiplayer /// The new beatmap availability state of the user. Task UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability); + Task UserExtraModsChanged(int userId, IEnumerable mods); + /// /// Signals that a match is to be started. This will *only* be sent to clients which are to begin loading at this point. /// diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index 09816974a7..484acfe957 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Threading.Tasks; +using osu.Game.Online.API; using osu.Game.Online.Rooms; namespace osu.Game.Online.Multiplayer @@ -47,6 +49,8 @@ namespace osu.Game.Online.Multiplayer /// The proposed new beatmap availability state. Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability); + Task ChangeExtraMods(IEnumerable newMods); + /// /// As the host of a room, start the match. /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index 2590acbc81..d7f7f9135e 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -4,7 +4,11 @@ #nullable enable using System; +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; using Newtonsoft.Json; +using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Users; @@ -22,6 +26,9 @@ namespace osu.Game.Online.Multiplayer /// public BeatmapAvailability BeatmapAvailability { get; set; } = BeatmapAvailability.LocallyAvailable(); + [NotNull] + public IEnumerable ExtraMods { get; set; } = Enumerable.Empty(); + public User? User { get; set; } [JsonConstructor] diff --git a/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs b/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs index e5b07ddfb4..33dcf1e8b4 100644 --- a/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs @@ -22,6 +22,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Users; using osu.Game.Utils; @@ -231,6 +232,10 @@ namespace osu.Game.Online.Multiplayer public abstract Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability); + public Task ChangeExtraMods(IEnumerable newMods) => ChangeExtraMods(newMods.Select(m => new APIMod(m)).ToList()); + + public abstract Task ChangeExtraMods(IEnumerable newMods); + public abstract Task StartMatch(); Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state) @@ -379,6 +384,27 @@ namespace osu.Game.Online.Multiplayer return Task.CompletedTask; } + public Task UserExtraModsChanged(int userId, IEnumerable mods) + { + if (Room == null) + return Task.CompletedTask; + + Scheduler.Add(() => + { + var user = Room?.Users.SingleOrDefault(u => u.UserID == userId); + + // errors here are not critical - user mods is mostly for display. + if (user == null) + return; + + user.ExtraMods = mods; + + RoomUpdated?.Invoke(); + }, false); + + return Task.CompletedTask; + } + Task IMultiplayerClient.LoadRequested() { if (Room == null) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 95dda1a051..c1025e73f8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -15,6 +16,7 @@ using osu.Game.Extensions; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays.Mods; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Match.Components; @@ -240,6 +242,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer base.LoadComplete(); Playlist.BindCollectionChanged(onPlaylistChanged, true); + ExtraMods.BindValueChanged(onExtraModsChanged); client.LoadRequested += onLoadRequested; @@ -285,6 +288,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } + private void onExtraModsChanged(ValueChangedEvent> extraMods) + { + if (client.Room == null) + return; + + client.ChangeExtraMods(extraMods.NewValue).CatchUnobservedExceptions(); + } + private void onReadyClick() { Debug.Assert(readyClickOperation == null); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index f99655e305..059e9e518d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -16,6 +17,8 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Screens.Play.HUD; using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; @@ -30,6 +33,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private RulesetStore rulesets { get; set; } + + private ModDisplay extraModsDisplay; private StateDisplay userStateDisplay; private SpriteIcon crown; @@ -122,11 +129,32 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants } } }, - userStateDisplay = new StateDisplay + new FillFlowContainer { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Margin = new MarginPadding { Right = 10 }, + Spacing = new Vector2(10), + Children = new Drawable[] + { + extraModsDisplay = new ModDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.5f), + ExpansionMode = ExpansionMode.AlwaysContracted, + DisplayUnrankedText = false, + ExpandOnAppear = false + }, + userStateDisplay = new StateDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AlwaysPresent = true + } + } } } } @@ -143,7 +171,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants const double fade_time = 50; + var ruleset = rulesets.GetRuleset(Room.Settings.RulesetID).CreateInstance(); + userStateDisplay.Status = User.State; + extraModsDisplay.Current.Value = User.ExtraMods.Select(m => m.ToMod(ruleset)).ToList(); if (Room.Host?.Equals(User) == true) crown.FadeIn(fade_time); diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 68d019bf71..2d5b07f056 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -26,6 +26,8 @@ namespace osu.Game.Screens.Play.HUD public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover; + public bool ExpandOnAppear = true; + private readonly Bindable> current = new Bindable>(); public Bindable> Current @@ -108,10 +110,14 @@ namespace osu.Game.Screens.Play.HUD else unrankedText.Hide(); - expand(); - - using (iconsContainer.BeginDelayedSequence(1200)) - contract(); + if (ExpandOnAppear) + { + expand(); + using (iconsContainer.BeginDelayedSequence(1200)) + contract(); + } + else + iconsContainer.TransformSpacingTo(new Vector2(-25, 0)); } private void expand() diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 7fbc770351..e699e7fb34 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -3,6 +3,7 @@ #nullable enable +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -11,6 +12,7 @@ using osu.Framework.Bindables; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Rulesets.Mods; using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer @@ -122,6 +124,21 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.CompletedTask; } + public void ChangeUserExtraMods(int userId, IEnumerable newMods) + => ChangeUserExtraMods(userId, newMods.Select(m => new APIMod(m)).ToList()); + + public void ChangeUserExtraMods(int userId, IEnumerable newMods) + { + Debug.Assert(Room != null); + ((IMultiplayerClient)this).UserExtraModsChanged(userId, newMods.ToList()); + } + + public override Task ChangeExtraMods(IEnumerable newMods) + { + ChangeUserExtraMods(api.LocalUser.Value.Id, newMods); + return Task.CompletedTask; + } + public override Task StartMatch() { Debug.Assert(Room != null);