1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 17:52:56 +08:00

Always add player instances at first, populate later

This commit is contained in:
smoogipoo 2021-04-16 12:25:29 +09:00
parent b391a8f94e
commit 5ac0eb02cd
3 changed files with 56 additions and 40 deletions

View File

@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public class TestSceneMultiplayerSpectator : MultiplayerTestScene
{
[Cached(typeof(SpectatorStreamingClient))]
private TestSpectatorStreamingClient testSpectatorStreamingClient = new TestSpectatorStreamingClient();
private TestSpectatorStreamingClient streamingClient = new TestSpectatorStreamingClient();
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@ -62,18 +62,42 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add streaming client", () =>
{
Remove(testSpectatorStreamingClient);
Add(testSpectatorStreamingClient);
Remove(streamingClient);
Add(streamingClient);
});
AddStep("finish previous gameplay", () =>
{
foreach (var id in playingUserIds)
testSpectatorStreamingClient.EndPlay(id, importedBeatmapId);
streamingClient.EndPlay(id, importedBeatmapId);
playingUserIds.Clear();
});
}
[Test]
public void TestDelayedStart()
{
AddStep("start players silently", () =>
{
Client.CurrentMatchPlayingUserIds.Add(55);
Client.CurrentMatchPlayingUserIds.Add(56);
playingUserIds.Add(55);
playingUserIds.Add(56);
nextFrame[55] = 0;
nextFrame[56] = 0;
});
loadSpectateScreen(false);
AddWaitStep("wait a bit", 10);
AddStep("load player 55", () => streamingClient.StartPlay(55, importedBeatmapId));
AddUntilStep("one player added", () => spectator.ChildrenOfType<Player>().Count() == 1);
AddWaitStep("wait a bit", 10);
AddStep("load player 56", () => streamingClient.StartPlay(56, importedBeatmapId));
AddUntilStep("two players added", () => spectator.ChildrenOfType<Player>().Count() == 2);
}
[Test]
public void TestGeneral()
{
@ -178,7 +202,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddWaitStep("wait a bit", 10);
}
private void loadSpectateScreen()
private void loadSpectateScreen(bool waitForPlayerLoad = true)
{
AddStep("load screen", () =>
{
@ -188,7 +212,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
LoadScreen(spectator = new MultiplayerSpectator(playingUserIds.ToArray()));
});
AddUntilStep("wait for screen load", () => spectator.LoadState == LoadState.Loaded && spectator.AllPlayersLoaded);
AddUntilStep("wait for screen load", () => spectator.LoadState == LoadState.Loaded && (!waitForPlayerLoad || spectator.AllPlayersLoaded));
}
private void start(int userId, int? beatmapId = null) => start(new[] { userId }, beatmapId);
@ -200,7 +224,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
foreach (int id in userIds)
{
Client.CurrentMatchPlayingUserIds.Add(id);
testSpectatorStreamingClient.StartPlay(id, beatmapId ?? importedBeatmapId);
streamingClient.StartPlay(id, beatmapId ?? importedBeatmapId);
playingUserIds.Add(id);
nextFrame[id] = 0;
}
@ -211,7 +235,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("end play", () =>
{
testSpectatorStreamingClient.EndPlay(userId, beatmapId ?? importedBeatmapId);
streamingClient.EndPlay(userId, beatmapId ?? importedBeatmapId);
playingUserIds.Remove(userId);
nextFrame.Remove(userId);
});
@ -225,7 +249,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
foreach (int id in userIds)
{
testSpectatorStreamingClient.SendFrames(id, nextFrame[id], count);
streamingClient.SendFrames(id, nextFrame[id], count);
nextFrame[id] += count;
}
});
@ -246,7 +270,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
private Player getPlayer(int userId) => getInstance(userId).ChildrenOfType<Player>().Single();
private PlayerInstance getInstance(int userId) => spectator.ChildrenOfType<PlayerInstance>().Single(p => p.User.Id == userId);
private PlayerInstance getInstance(int userId) => spectator.ChildrenOfType<PlayerInstance>().Single(p => p.UserId == userId);
public class TestSpectatorStreamingClient : SpectatorStreamingClient
{
@ -297,7 +321,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public override void WatchUser(int userId)
{
if (userSentStateDictionary[userId])
if (userSentStateDictionary.TryGetValue(userId, out var sent) && sent)
{
// usually the server would do this.
sendState(userId, userBeatmapDictionary[userId]);

View File

@ -32,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
public MultiplayerSpectator(int[] userIds)
: base(userIds.AsSpan().Slice(0, Math.Min(16, userIds.Length)).ToArray())
{
instances = new PlayerInstance[userIds.Length];
instances = new PlayerInstance[UserIds.Length];
}
[BackgroundDependencyLoader]
@ -70,6 +70,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
masterClockContainer
};
for (int i = 0; i < UserIds.Length; i++)
grid.Add(instances[i] = new PlayerInstance(UserIds[i], new SpectatorCatchUpSlaveClock(masterClockContainer.GameplayClock)));
// Todo: This is not quite correct - it should be per-user to adjust for other mod combinations.
var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
var scoreProcessor = Ruleset.Value.CreateInstance().CreateScoreProcessor();
@ -93,24 +96,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
protected override void StartGameplay(int userId, GameplayState gameplayState)
{
int userIndex = getIndexForUser(userId);
var existingInstance = instances[userIndex];
if (existingInstance != null)
{
grid.Remove(existingInstance);
syncManager.RemoveSlave(existingInstance.GameplayClock);
leaderboard.RemoveClock(existingInstance.User.Id);
}
var instance = instances[userIndex];
syncManager.RemoveSlave(instance.GameplayClock);
leaderboard.RemoveClock(instance.UserId);
LoadComponentAsync(instances[userIndex] = new PlayerInstance(gameplayState.Score, new SpectatorCatchUpSlaveClock(masterClockContainer.GameplayClock)), d =>
{
if (instances[userIndex] == d)
{
grid.Add(d);
syncManager.AddSlave(d.GameplayClock);
leaderboard.AddClock(d.User.Id, d.GameplayClock);
}
});
instance.LoadPlayer(gameplayState.Score);
syncManager.AddSlave(instance.GameplayClock);
leaderboard.AddClock(instance.UserId, instance.GameplayClock);
}
protected override void EndGameplay(int userId)

View File

@ -8,7 +8,6 @@ using osu.Game.Beatmaps;
using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate.Sync;
using osu.Game.Screens.Play;
using osu.Game.Users;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
{
@ -16,30 +15,30 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
{
public bool PlayerLoaded => stack?.CurrentScreen is Player;
public User User => Score.ScoreInfo.User;
public WorkingBeatmap Beatmap { get; private set; }
public readonly Score Score;
public readonly int UserId;
public readonly SpectatorCatchUpSlaveClock GameplayClock;
public Score Score { get; private set; }
[Resolved]
private BeatmapManager beatmapManager { get; set; }
private OsuScreenStack stack;
public PlayerInstance(Score score, SpectatorCatchUpSlaveClock gameplayClock)
public PlayerInstance(int userId, SpectatorCatchUpSlaveClock gameplayClock)
{
Score = score;
UserId = userId;
GameplayClock = gameplayClock;
RelativeSizeAxes = Axes.Both;
Masking = true;
}
[BackgroundDependencyLoader]
private void load(BeatmapManager beatmapManager)
public void LoadPlayer(Score score)
{
Beatmap = beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.Beatmap, bypassCache: true);
Score = score;
InternalChild = new GameplayIsolationContainer(Beatmap, Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods)
InternalChild = new GameplayIsolationContainer(beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.Beatmap, bypassCache: true), Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods)
{
RelativeSizeAxes = Axes.Both,
Child = new DrawSizePreservingFillContainer