Merge branch 'abstract-room-manager' into stateful-multiplayer-client

This commit is contained in:
smoogipoo
2020-12-20 23:10:05 +09:00
30 changed files with 872 additions and 241 deletions

View File

@ -61,12 +61,12 @@ namespace osu.Game.Tests.Visual.Components
{
createPoller(true);
AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust);
AddStep("set poll interval to 1", () => poller.TimeBetweenPolls.Value = TimePerAction * safety_adjust);
checkCount(1);
checkCount(2);
checkCount(3);
AddStep("set poll interval to 5", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust * 5);
AddStep("set poll interval to 5", () => poller.TimeBetweenPolls.Value = TimePerAction * safety_adjust * 5);
checkCount(4);
checkCount(4);
checkCount(4);
@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Components
checkCount(5);
checkCount(5);
AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust);
AddStep("set poll interval to 1", () => poller.TimeBetweenPolls.Value = TimePerAction * safety_adjust);
checkCount(6);
checkCount(7);
}
@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual.Components
{
createPoller(false);
AddStep("set poll interval to 1", () => poller.TimeBetweenPolls = TimePerAction * safety_adjust * 5);
AddStep("set poll interval to 1", () => poller.TimeBetweenPolls.Value = TimePerAction * safety_adjust * 5);
checkCount(0);
skip();
checkCount(0);
@ -141,7 +141,7 @@ namespace osu.Game.Tests.Visual.Components
public class TestSlowPoller : TestPoller
{
protected override Task Poll() => Task.Delay((int)(TimeBetweenPolls / 2f / Clock.Rate)).ContinueWith(_ => base.Poll());
protected override Task Poll() => Task.Delay((int)(TimeBetweenPolls.Value / 2f / Clock.Rate)).ContinueWith(_ => base.Poll());
}
}
}

View File

@ -10,6 +10,8 @@ using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
using osu.Game.Storyboards;
using osuTK;
@ -50,7 +52,7 @@ namespace osu.Game.Tests.Visual.Gameplay
cancel();
complete();
AddUntilStep("attempted to push ranking", () => ((FakeRankingPushPlayer)Player).GotoRankingInvoked);
AddUntilStep("attempted to push ranking", () => ((FakeRankingPushPlayer)Player).ResultsCreated);
}
/// <summary>
@ -84,7 +86,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
// wait to ensure there was no attempt of pushing the results screen.
AddWaitStep("wait", resultsDisplayWaitCount);
AddAssert("no attempt to push ranking", () => !((FakeRankingPushPlayer)Player).GotoRankingInvoked);
AddAssert("no attempt to push ranking", () => !((FakeRankingPushPlayer)Player).ResultsCreated);
}
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
@ -110,16 +112,18 @@ namespace osu.Game.Tests.Visual.Gameplay
public class FakeRankingPushPlayer : TestPlayer
{
public bool GotoRankingInvoked;
public bool ResultsCreated { get; private set; }
public FakeRankingPushPlayer()
: base(true, true)
{
}
protected override void GotoRanking()
protected override ResultsScreen CreateResults(ScoreInfo score)
{
GotoRankingInvoked = true;
var results = base.CreateResults(score);
ResultsCreated = true;
return results;
}
}
}

View File

@ -6,6 +6,7 @@ using NUnit.Framework;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Screens.Play.HUD;
using osu.Game.Users;
using osuTK;
@ -26,7 +27,6 @@ namespace osu.Game.Tests.Visual.Gameplay
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(2),
RelativeSizeAxes = Axes.X,
});
}
@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay
playerScore.Value = 1222333;
});
AddStep("add player user", () => leaderboard.AddPlayer(playerScore, new User { Username = "You" }));
AddStep("add local player", () => createLeaderboardScore(playerScore, new User { Username = "You", Id = 3 }, true));
AddSliderStep("set player score", 50, 5000000, 1222333, v => playerScore.Value = v);
}
@ -49,8 +49,8 @@ namespace osu.Game.Tests.Visual.Gameplay
var player2Score = new BindableDouble(1234567);
var player3Score = new BindableDouble(1111111);
AddStep("add player 2", () => leaderboard.AddPlayer(player2Score, new User { Username = "Player 2" }));
AddStep("add player 3", () => leaderboard.AddPlayer(player3Score, new User { Username = "Player 3" }));
AddStep("add player 2", () => createLeaderboardScore(player2Score, new User { Username = "Player 2" }));
AddStep("add player 3", () => createLeaderboardScore(player3Score, new User { Username = "Player 3" }));
AddAssert("is player 2 position #1", () => leaderboard.CheckPositionByUsername("Player 2", 1));
AddAssert("is player position #2", () => leaderboard.CheckPositionByUsername("You", 2));
@ -67,6 +67,30 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("is player 2 position #3", () => leaderboard.CheckPositionByUsername("Player 2", 3));
}
[Test]
public void TestRandomScores()
{
int playerNumber = 1;
AddRepeatStep("add player with random score", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 10);
}
[Test]
public void TestExistingUsers()
{
AddStep("add peppy", () => createRandomScore(new User { Username = "peppy", Id = 2 }));
AddStep("add smoogipoo", () => createRandomScore(new User { Username = "smoogipoo", Id = 1040328 }));
AddStep("add flyte", () => createRandomScore(new User { Username = "flyte", Id = 3103765 }));
AddStep("add frenzibyte", () => createRandomScore(new User { Username = "frenzibyte", Id = 14210502 }));
}
private void createRandomScore(User user) => createLeaderboardScore(new BindableDouble(RNG.Next(0, 5_000_000)), user);
private void createLeaderboardScore(BindableDouble score, User user, bool isTracked = false)
{
var leaderboardScore = leaderboard.AddPlayer(user, isTracked);
leaderboardScore.TotalScore.BindTo(score);
}
private class TestGameplayLeaderboard : GameplayLeaderboard
{
public bool CheckPositionByUsername(string username, int? expectedPosition)

View File

@ -0,0 +1,155 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Database;
using osu.Game.Online.Spectator;
using osu.Game.Replays.Legacy;
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.Online;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneMultiplayerGameplayLeaderboard : OsuTestScene
{
[Cached(typeof(SpectatorStreamingClient))]
private TestMultiplayerStreaming streamingClient = new TestMultiplayerStreaming(16);
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestSceneCurrentlyPlayingDisplay.TestUserLookupCache();
private MultiplayerGameplayLeaderboard leaderboard;
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
public TestSceneMultiplayerGameplayLeaderboard()
{
base.Content.Children = new Drawable[]
{
streamingClient,
lookupCache,
Content
};
}
[SetUpSteps]
public void SetUpSteps()
{
AddStep("create leaderboard", () =>
{
OsuScoreProcessor scoreProcessor;
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
streamingClient.Start(Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
Children = new Drawable[]
{
scoreProcessor = new OsuScoreProcessor(),
};
scoreProcessor.ApplyBeatmap(playable);
LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, streamingClient.PlayingUsers.ToArray())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}, Add);
});
AddUntilStep("wait for load", () => leaderboard.IsLoaded);
}
[Test]
public void TestScoreUpdates()
{
AddRepeatStep("update state", () => streamingClient.RandomlyUpdateState(), 100);
}
public class TestMultiplayerStreaming : SpectatorStreamingClient
{
public new BindableList<int> PlayingUsers => (BindableList<int>)base.PlayingUsers;
private readonly int totalUsers;
public TestMultiplayerStreaming(int totalUsers)
{
this.totalUsers = totalUsers;
}
public void Start(int beatmapId)
{
for (int i = 0; i < totalUsers; i++)
{
((ISpectatorClient)this).UserBeganPlaying(i, new SpectatorState
{
BeatmapID = beatmapId,
RulesetID = 0,
});
}
}
private readonly Dictionary<int, FrameHeader> lastHeaders = new Dictionary<int, FrameHeader>();
public void RandomlyUpdateState()
{
foreach (var userId in PlayingUsers)
{
if (RNG.NextBool())
continue;
if (!lastHeaders.TryGetValue(userId, out var header))
{
lastHeaders[userId] = header = new FrameHeader(new ScoreInfo
{
Statistics = new Dictionary<HitResult, int>
{
[HitResult.Miss] = 0,
[HitResult.Meh] = 0,
[HitResult.Great] = 0
}
});
}
switch (RNG.Next(0, 3))
{
case 0:
header.Combo = 0;
header.Statistics[HitResult.Miss]++;
break;
case 1:
header.Combo++;
header.MaxCombo = Math.Max(header.MaxCombo, header.Combo);
header.Statistics[HitResult.Meh]++;
break;
default:
header.Combo++;
header.MaxCombo = Math.Max(header.MaxCombo, header.Combo);
header.Statistics[HitResult.Great]++;
break;
}
((ISpectatorClient)this).UserSentFrames(userId, new FrameDataBundle(header, Array.Empty<LegacyReplayFrame>()));
}
}
protected override Task Connect() => Task.CompletedTask;
}
}
}

View File

@ -232,7 +232,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public class TestSpectatorStreamingClient : SpectatorStreamingClient
{
public readonly User StreamingUser = new User { Id = 1234, Username = "Test user" };
public readonly User StreamingUser = new User { Id = 55, Username = "Test user" };
public new BindableList<int> PlayingUsers => (BindableList<int>)base.PlayingUsers;

View File

@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public readonly BindableList<Room> Rooms = new BindableList<Room>();
public Bindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
IBindableList<Room> IRoomManager.Rooms => Rooms;

View File

@ -131,7 +131,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
remove { }
}
public Bindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
public IBindableList<Room> Rooms => null;

View File

@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
remove => throw new NotImplementedException();
}
public Bindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
public IBindableList<Room> Rooms { get; } = new BindableList<Room>();

View File

@ -69,8 +69,32 @@ namespace osu.Game.Tests.Visual.Online
internal class TestUserLookupCache : UserLookupCache
{
private static readonly string[] usernames =
{
"fieryrage",
"Kerensa",
"MillhioreF",
"Player01",
"smoogipoo",
"Ephemeral",
"BTMC",
"Cilvery",
"m980",
"HappyStick",
"LittleEndu",
"frenzibyte",
"Zallius",
"BanchoBot",
"rocketminer210",
"pishifat"
};
protected override Task<User> ComputeValueAsync(int lookup, CancellationToken token = default)
=> Task.FromResult(new User { Username = "peppy", Id = 2 });
=> Task.FromResult(new User
{
Id = lookup,
Username = usernames[lookup % usernames.Length],
});
}
}
}