diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 7ce0c6a94d..77a06e5746 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -15,6 +15,7 @@ using osu.Game.Configuration; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; +using osu.Game.Online.Rooms; using osu.Game.Rulesets.UI; using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; @@ -377,7 +378,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Beatmap.Value = beatmapManager.GetWorkingBeatmap(importedBeatmap); Ruleset.Value = importedBeatmap.Ruleset; - LoadScreen(spectatorScreen = new TestMultiSpectatorScreen(playingUsers.ToArray(), gameplayStartTime)); + LoadScreen(spectatorScreen = new TestMultiSpectatorScreen(SelectedRoom.Value, playingUsers.ToArray(), gameplayStartTime)); }); AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded && (!waitForPlayerLoad || spectatorScreen.AllPlayersLoaded)); @@ -465,8 +466,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { private readonly double? gameplayStartTime; - public TestMultiSpectatorScreen(MultiplayerRoomUser[] users, double? gameplayStartTime = null) - : base(users) + public TestMultiSpectatorScreen(Room room, MultiplayerRoomUser[] users, double? gameplayStartTime = null) + : base(room, users) { this.gameplayStartTime = gameplayStartTime; } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fa5a336b7c..fb81e4fd14 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -838,7 +838,8 @@ namespace osu.Game channelManager.HighPollRate.Value = chatOverlay.State.Value == Visibility.Visible || API.Activity.Value is UserActivity.InLobby - || API.Activity.Value is UserActivity.InMultiplayerGame; + || API.Activity.Value is UserActivity.InMultiplayerGame + || API.Activity.Value is UserActivity.SpectatingMultiplayerGame; } Add(difficultyRecommender); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 53fd111c27..d08a63e21f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.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 JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -15,10 +16,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { public class GameplayChatDisplay : MatchChatDisplay, IKeyBindingHandler { - [Resolved] + [Resolved(CanBeNull = true)] + [CanBeNull] private ILocalUserPlayInfo localUserInfo { get; set; } - private IBindable localUserPlaying = new Bindable(); + private readonly IBindable localUserPlaying = new Bindable(); public override bool PropagatePositionalInputSubTree => !localUserPlaying.Value; @@ -46,7 +48,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { base.LoadComplete(); - localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy(); + if (localUserInfo != null) + localUserPlaying.BindTo(localUserInfo.IsPlaying); + localUserPlaying.BindValueChanged(playing => { // for now let's never hold focus. this avoid misdirected gameplay keys entering chat. diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 429b0ad89b..c78dcb7cb6 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -449,7 +449,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer switch (client.LocalUser.State) { case MultiplayerUserState.Spectating: - return new MultiSpectatorScreen(users.Take(PlayerGrid.MAX_PLAYERS).ToArray()); + return new MultiSpectatorScreen(Room, users.Take(PlayerGrid.MAX_PLAYERS).ToArray()); default: return new MultiplayerPlayerLoader(() => new MultiplayerPlayer(Room, SelectedItem.Value, users)); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index e5eeeb3448..3bb76c4a76 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -11,10 +11,13 @@ using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; +using osu.Game.Online.Rooms; using osu.Game.Online.Spectator; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Spectate; +using osu.Game.Users; +using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { @@ -34,6 +37,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// public bool AllPlayersLoaded => instances.All(p => p?.PlayerLoaded == true); + protected override UserActivity InitialActivity => new UserActivity.SpectatingMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); + [Resolved] private OsuColour colours { get; set; } @@ -48,15 +53,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate private PlayerArea currentAudioSource; private bool canStartMasterClock; + private readonly Room room; private readonly MultiplayerRoomUser[] users; /// /// Creates a new . /// + /// The room. /// The players to spectate. - public MultiSpectatorScreen(MultiplayerRoomUser[] users) + public MultiSpectatorScreen(Room room, MultiplayerRoomUser[] users) : base(users.Select(u => u.UserID).ToArray()) { + this.room = room; this.users = users; instances = new PlayerArea[Users.Count]; @@ -65,7 +73,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [BackgroundDependencyLoader] private void load() { - Container leaderboardContainer; + FillFlowContainer leaderboardFlow; Container scoreDisplayContainer; masterClockContainer = CreateMasterGameplayClockContainer(Beatmap.Value); @@ -97,10 +105,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { new Drawable[] { - leaderboardContainer = new Container + leaderboardFlow = new FillFlowContainer { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(5) }, grid = new PlayerGrid { RelativeSizeAxes = Axes.Both } } @@ -125,14 +136,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(scoreProcessor, users) { Expanded = { Value = true }, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, }, l => { foreach (var instance in instances) leaderboard.AddClock(instance.UserId, instance.GameplayClock); - leaderboardContainer.Add(leaderboard); + leaderboardFlow.Insert(0, leaderboard); if (leaderboard.TeamScores.Count == 2) { @@ -143,6 +152,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate }, scoreDisplayContainer.Add); } }); + + LoadComponentAsync(new GameplayChatDisplay(room) + { + Expanded = { Value = true }, + }, chat => leaderboardFlow.Insert(1, chat)); } protected override void LoadComplete() diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 516aa80652..2f945d6e1c 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -50,6 +50,16 @@ namespace osu.Game.Users public override string Status => $@"{base.Status} with others"; } + public class SpectatingMultiplayerGame : InGame + { + public SpectatingMultiplayerGame(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset) + : base(beatmapInfo, ruleset) + { + } + + public override string Status => $"Watching others {base.Status.ToLowerInvariant()}"; + } + public class InPlaylistGame : InGame { public InPlaylistGame(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset)