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

View File

@ -2,12 +2,16 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Spectator;
using osu.Game.Rulesets.Scoring;
@ -18,10 +22,21 @@ namespace osu.Game.Screens.Play.HUD
{
private readonly ScoreProcessor scoreProcessor;
private readonly int[] userIds;
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>
/// Construct a new leaderboard.
/// </summary>
@ -33,32 +48,24 @@ namespace osu.Game.Screens.Play.HUD
this.scoreProcessor = scoreProcessor;
// 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]
private void load(OsuConfigManager config, IAPIProvider api)
{
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.
var resolvedUser = userLookupCache.GetUserAsync(user).Result;
var resolvedUser = userLookupCache.GetUserAsync(userId).Result;
var trackedUser = new TrackedUserData();
userScores[user] = trackedUser;
userScores[userId] = trackedUser;
var leaderboardScore = AddPlayer(resolvedUser, resolvedUser.Id == api.LocalUser.Value.Id);
((IBindable<double>)leaderboardScore.Accuracy).BindTo(trackedUser.Accuracy);
@ -70,6 +77,28 @@ namespace osu.Game.Screens.Play.HUD
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)
{
foreach (var trackedData in userScores.Values)
@ -91,7 +120,7 @@ namespace osu.Game.Screens.Play.HUD
if (streamingClient != null)
{
foreach (var user in userIds)
foreach (var user in playingUsers)
{
streamingClient.StopWatchingUser(user);
}