1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 21:12:55 +08:00

Fix multiplayer leaderboard not unsubscribing from quit users

This commit is contained in:
Dean Herbert 2020-12-26 11:34:05 +09:00
parent ff811e9a88
commit ff57562956
2 changed files with 48 additions and 18 deletions

View File

@ -20,11 +20,12 @@ using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osu.Game.Tests.Visual.Multiplayer;
using osu.Game.Tests.Visual.Online; using osu.Game.Tests.Visual.Online;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
public class TestSceneMultiplayerGameplayLeaderboard : OsuTestScene public class TestSceneMultiplayerGameplayLeaderboard : MultiplayerTestScene
{ {
[Cached(typeof(SpectatorStreamingClient))] [Cached(typeof(SpectatorStreamingClient))]
private TestMultiplayerStreaming streamingClient = new TestMultiplayerStreaming(16); private TestMultiplayerStreaming streamingClient = new TestMultiplayerStreaming(16);
@ -47,7 +48,7 @@ namespace osu.Game.Tests.Visual.Gameplay
} }
[SetUpSteps] [SetUpSteps]
public void SetUpSteps() public override void SetUpSteps()
{ {
AddStep("create leaderboard", () => AddStep("create leaderboard", () =>
{ {

View File

@ -2,12 +2,16 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Spectator; using osu.Game.Online.Spectator;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -18,10 +22,21 @@ namespace osu.Game.Screens.Play.HUD
{ {
private readonly ScoreProcessor scoreProcessor; private readonly ScoreProcessor scoreProcessor;
private readonly int[] userIds;
private readonly Dictionary<int, TrackedUserData> userScores = new Dictionary<int, TrackedUserData>(); private readonly Dictionary<int, TrackedUserData> userScores = new Dictionary<int, TrackedUserData>();
[Resolved]
private SpectatorStreamingClient streamingClient { get; set; }
[Resolved]
private StatefulMultiplayerClient multiplayerClient { get; set; }
[Resolved]
private UserLookupCache userLookupCache { get; set; }
private Bindable<ScoringMode> scoringMode;
private readonly BindableList<int> playingUsers;
/// <summary> /// <summary>
/// Construct a new leaderboard. /// Construct a new leaderboard.
/// </summary> /// </summary>
@ -33,32 +48,24 @@ namespace osu.Game.Screens.Play.HUD
this.scoreProcessor = scoreProcessor; this.scoreProcessor = scoreProcessor;
// todo: this will likely be passed in as User instances. // todo: this will likely be passed in as User instances.
this.userIds = userIds; playingUsers = new BindableList<int>(userIds);
} }
[Resolved]
private SpectatorStreamingClient streamingClient { get; set; }
[Resolved]
private UserLookupCache userLookupCache { get; set; }
private Bindable<ScoringMode> scoringMode;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config, IAPIProvider api) private void load(OsuConfigManager config, IAPIProvider api)
{ {
streamingClient.OnNewFrames += handleIncomingFrames; streamingClient.OnNewFrames += handleIncomingFrames;
foreach (var user in userIds) foreach (var userId in playingUsers)
{ {
streamingClient.WatchUser(user); streamingClient.WatchUser(userId);
// probably won't be required in the final implementation. // probably won't be required in the final implementation.
var resolvedUser = userLookupCache.GetUserAsync(user).Result; var resolvedUser = userLookupCache.GetUserAsync(userId).Result;
var trackedUser = new TrackedUserData(); var trackedUser = new TrackedUserData();
userScores[user] = trackedUser; userScores[userId] = trackedUser;
var leaderboardScore = AddPlayer(resolvedUser, resolvedUser.Id == api.LocalUser.Value.Id); var leaderboardScore = AddPlayer(resolvedUser, resolvedUser.Id == api.LocalUser.Value.Id);
((IBindable<double>)leaderboardScore.Accuracy).BindTo(trackedUser.Accuracy); ((IBindable<double>)leaderboardScore.Accuracy).BindTo(trackedUser.Accuracy);
@ -70,6 +77,28 @@ namespace osu.Game.Screens.Play.HUD
scoringMode.BindValueChanged(updateAllScores, true); scoringMode.BindValueChanged(updateAllScores, true);
} }
protected override void LoadComplete()
{
base.LoadComplete();
playingUsers.BindCollectionChanged(usersChanged);
playingUsers.BindTo(multiplayerClient.PlayingUsers);
}
private void usersChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
foreach (var userId in e.OldItems.OfType<int>())
{
streamingClient.StopWatchingUser(userId);
}
break;
}
}
private void updateAllScores(ValueChangedEvent<ScoringMode> mode) private void updateAllScores(ValueChangedEvent<ScoringMode> mode)
{ {
foreach (var trackedData in userScores.Values) foreach (var trackedData in userScores.Values)
@ -91,7 +120,7 @@ namespace osu.Game.Screens.Play.HUD
if (streamingClient != null) if (streamingClient != null)
{ {
foreach (var user in userIds) foreach (var user in playingUsers)
{ {
streamingClient.StopWatchingUser(user); streamingClient.StopWatchingUser(user);
} }