mirror of
https://github.com/ppy/osu.git
synced 2026-05-17 20:24:01 +08:00
31c1168d76
- Last part of / closes https://github.com/ppy/osu-server-spectator/issues/406. - Remaining work on slots will be tracked in https://github.com/ppy/osu-server-spectator/issues/405. This PR is a corollary of https://github.com/ppy/osu-server-spectator/pull/453 and all of the dispensations referee users in a multiplayer have received therein. The goal here is to allow access to all relevant room management functions even if the referee in question isn't host, as well as to disallow access to all non-relevant functions to do with the actual match gameplay. I'm not going to lie, this logic *is* ugly. I would argue that it already *was* ugly on `master` and my goal was to operate with as light a touch as possible myself. But you could see this as copping out and that I should try to refactor some of this. I will try - but only after someone else's seen the initial approach and deemed it unsuitable. The logic in `MatchStartControl` is awful - there are so many moving pieces of state that dictate what can happen when with all the buttons, and yes, I am making it worse here. This time there is some test coverage. Not everything is covered, but the coverage should be on par in all components and pieces of relevant logic I touched that already had tests covering them. On that note, please forgive the diffstat size, but the tests *are* most of that size. --------- Co-authored-by: Dean Herbert <pe@ppy.sh>
568 lines
24 KiB
C#
568 lines
24 KiB
C#
// 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.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using NUnit.Framework;
|
|
using osu.Framework.Extensions.ObjectExtensions;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Sprites;
|
|
using osu.Framework.Testing;
|
|
using osu.Framework.Utils;
|
|
using osu.Game.Graphics.Cursor;
|
|
using osu.Game.Graphics.UserInterface;
|
|
using osu.Game.Online;
|
|
using osu.Game.Online.API;
|
|
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.Catch.Mods;
|
|
using osu.Game.Rulesets.Mods;
|
|
using osu.Game.Rulesets.Osu.Mods;
|
|
using osu.Game.Rulesets.Taiko.Mods;
|
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
|
|
using osu.Game.Tests.Resources;
|
|
using osu.Game.Users;
|
|
using osuTK;
|
|
using osuTK.Input;
|
|
|
|
namespace osu.Game.Tests.Visual.Multiplayer
|
|
{
|
|
public partial class TestSceneMultiplayerParticipantsList : MultiplayerTestScene
|
|
{
|
|
private void setUpList()
|
|
{
|
|
AddStep("join room", () => JoinRoom(CreateDefaultRoom()));
|
|
WaitForJoined();
|
|
createNewParticipantsList();
|
|
}
|
|
|
|
[Test]
|
|
public void TestAddUser()
|
|
{
|
|
setUpList();
|
|
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 1);
|
|
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}));
|
|
|
|
AddAssert("two unique panels", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 2);
|
|
}
|
|
|
|
[Test]
|
|
public void TestAddReferee()
|
|
{
|
|
setUpList();
|
|
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 1);
|
|
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(3)
|
|
{
|
|
User = new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
},
|
|
Role = MultiplayerRoomUserRole.Referee
|
|
}));
|
|
|
|
AddAssert("two unique panels", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 2);
|
|
}
|
|
|
|
[Test]
|
|
public void TestAddUnresolvedUser()
|
|
{
|
|
setUpList();
|
|
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 1);
|
|
|
|
AddStep("add non-resolvable user", () => MultiplayerClient.TestAddUnresolvedUser());
|
|
AddUntilStep("null user added", () => MultiplayerClient.ClientRoom.AsNonNull().Users.Count(u => u.User == null) == 1);
|
|
|
|
AddUntilStep("two unique panels", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 2);
|
|
|
|
AddStep("kick null user", () => this.ChildrenOfType<ParticipantPanel>().Single(p => p.Current.Value.User == null)
|
|
.ChildrenOfType<ParticipantPanel.KickButton>().Single().TriggerClick());
|
|
|
|
AddUntilStep("null user kicked", () => MultiplayerClient.ClientRoom.AsNonNull().Users.Count == 1);
|
|
}
|
|
|
|
[Test]
|
|
public void TestRemoveUser()
|
|
{
|
|
setUpList();
|
|
|
|
APIUser? secondUser = null;
|
|
|
|
AddStep("add a user", () =>
|
|
{
|
|
MultiplayerClient.AddUser(secondUser = new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
});
|
|
});
|
|
|
|
AddStep("remove host", () => MultiplayerClient.RemoveUser(API.LocalUser.Value));
|
|
|
|
AddAssert("single panel is for second user", () => this.ChildrenOfType<ParticipantPanel>().Single().Current.Value.UserID == secondUser?.Id);
|
|
}
|
|
|
|
[Test]
|
|
public void TestGameStateHasPriorityOverDownloadState()
|
|
{
|
|
setUpList();
|
|
AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
|
checkProgressBarVisibility(true);
|
|
|
|
AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Results));
|
|
checkProgressBarVisibility(false);
|
|
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
|
|
|
AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle));
|
|
checkProgressBarVisibility(true);
|
|
}
|
|
|
|
[Test]
|
|
public void TestCorrectInitialState()
|
|
{
|
|
setUpList();
|
|
AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
|
createNewParticipantsList();
|
|
checkProgressBarVisibility(true);
|
|
}
|
|
|
|
[Test]
|
|
public void TestBeatmapDownloadingStates()
|
|
{
|
|
setUpList();
|
|
AddStep("set to unknown", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Unknown()));
|
|
AddStep("set to no map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded()));
|
|
AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
|
|
|
checkProgressBarVisibility(true);
|
|
|
|
AddRepeatStep("increment progress", () =>
|
|
{
|
|
float progress = this.ChildrenOfType<ParticipantPanel>().Single().Current.Value.BeatmapAvailability.DownloadProgress ?? 0;
|
|
MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f)));
|
|
}, 25);
|
|
|
|
AddAssert("progress bar increased", () => this.ChildrenOfType<ProgressBar>().Single().Current.Value > 0);
|
|
|
|
AddStep("set to importing map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Importing()));
|
|
checkProgressBarVisibility(false);
|
|
|
|
AddStep("set to available", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()));
|
|
}
|
|
|
|
[Test]
|
|
public void TestToggleReadyState()
|
|
{
|
|
setUpList();
|
|
AddAssert("ready mark invisible", () => !this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
|
|
|
AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Ready));
|
|
AddUntilStep("ready mark visible", () => this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
|
|
|
AddStep("make user idle", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle));
|
|
AddUntilStep("ready mark invisible", () => !this.ChildrenOfType<StateDisplay>().Single().IsPresent);
|
|
}
|
|
|
|
[Test]
|
|
public void TestToggleSpectateState()
|
|
{
|
|
setUpList();
|
|
AddStep("make user spectating", () => MultiplayerClient.ChangeState(MultiplayerUserState.Spectating));
|
|
AddStep("make user idle", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle));
|
|
}
|
|
|
|
[Test]
|
|
public void TestCrownChangesStateWhenHostTransferred()
|
|
{
|
|
setUpList();
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}));
|
|
|
|
AddUntilStep("first user crown visible",
|
|
() => this.ChildrenOfType<ParticipantPanel>().Single(p => p.Current.Value.UserID == 1001).ChildrenOfType<SpriteIcon>().First().Alpha == 1);
|
|
AddUntilStep("second user crown hidden",
|
|
() => this.ChildrenOfType<ParticipantPanel>().Single(p => p.Current.Value.UserID == 3).ChildrenOfType<SpriteIcon>().First().Alpha == 0);
|
|
|
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
|
|
|
AddUntilStep("first user crown visible",
|
|
() => this.ChildrenOfType<ParticipantPanel>().Single(p => p.Current.Value.UserID == 1001).ChildrenOfType<SpriteIcon>().First().Alpha == 0);
|
|
AddUntilStep("second user crown hidden",
|
|
() => this.ChildrenOfType<ParticipantPanel>().Single(p => p.Current.Value.UserID == 3).ChildrenOfType<SpriteIcon>().First().Alpha == 1);
|
|
}
|
|
|
|
[Test]
|
|
public void TestHostGetsPinnedToTop()
|
|
{
|
|
setUpList();
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}));
|
|
|
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
|
AddAssert("second user above first", () =>
|
|
{
|
|
var first = this.ChildrenOfType<ParticipantPanel>().Single(u => u.Current.Value.UserID == 1001);
|
|
var second = this.ChildrenOfType<ParticipantPanel>().Single(u => u.Current.Value.UserID == 3);
|
|
return second.ScreenSpaceDrawQuad.TopLeft.Y < first.ScreenSpaceDrawQuad.TopLeft.Y;
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void TestKickButtonPresentWhenHost()
|
|
{
|
|
setUpList();
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}));
|
|
|
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
|
|
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
|
|
|
AddUntilStep("kick buttons not visible", () => !this.ChildrenOfType<ParticipantPanel.KickButton>().Any(d => d.IsPresent));
|
|
|
|
AddStep("make local user host again", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id));
|
|
|
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
|
}
|
|
|
|
[Test]
|
|
public void TestKickButtonPresentWhenReferee()
|
|
{
|
|
AddStep("set up referee", () => MultiplayerClient.RoomSetupAction = r => r.Host!.Role = MultiplayerRoomUserRole.Referee);
|
|
setUpList();
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}));
|
|
|
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
|
|
|
AddStep("make second user host", () => MultiplayerClient.TransferHost(3));
|
|
|
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
|
|
|
AddStep("make local user host again", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id));
|
|
|
|
AddUntilStep("kick buttons visible", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Count(d => d.IsPresent) == 1);
|
|
}
|
|
|
|
[Test]
|
|
public void TestKickButtonKicks()
|
|
{
|
|
setUpList();
|
|
AddStep("add user", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 3,
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}));
|
|
|
|
AddStep("kick second user", () => this.ChildrenOfType<ParticipantPanel.KickButton>().Single(d => d.IsPresent).TriggerClick());
|
|
|
|
AddUntilStep("second user kicked", () => MultiplayerClient.ClientRoom?.Users.Single().UserID == API.LocalUser.Value.Id);
|
|
}
|
|
|
|
[Test]
|
|
public void TestManyUsers()
|
|
{
|
|
const int users_count = 200;
|
|
|
|
setUpList();
|
|
AddStep("add many users", () =>
|
|
{
|
|
for (int i = 0; i < users_count; i++)
|
|
{
|
|
MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = i,
|
|
Username = $"User {i}",
|
|
RulesetsStatistics = new Dictionary<string, UserStatistics>
|
|
{
|
|
{
|
|
Ruleset.Value.ShortName,
|
|
new UserStatistics { GlobalRank = RNG.Next(1, 100000), }
|
|
}
|
|
},
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
});
|
|
|
|
MultiplayerClient.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1));
|
|
|
|
if (RNG.NextBool())
|
|
{
|
|
var beatmapState = (DownloadState)RNG.Next(0, (int)DownloadState.LocallyAvailable + 1);
|
|
|
|
switch (beatmapState)
|
|
{
|
|
case DownloadState.NotDownloaded:
|
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.NotDownloaded());
|
|
break;
|
|
|
|
case DownloadState.Downloading:
|
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Downloading(RNG.NextSingle()));
|
|
break;
|
|
|
|
case DownloadState.Importing:
|
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Importing());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
AddRepeatStep("switch hosts", () => MultiplayerClient.TransferHost(RNG.Next(0, users_count)), 10);
|
|
AddStep("give host back", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id));
|
|
|
|
AddRepeatStep("perform many random state changes at once", () =>
|
|
{
|
|
for (int i = 0; i < users_count; ++i)
|
|
{
|
|
MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.LocallyAvailable());
|
|
MultiplayerClient.ChangeUserState(i, RNG.NextBool() ? MultiplayerUserState.Idle : MultiplayerUserState.Ready);
|
|
}
|
|
}, 100);
|
|
}
|
|
|
|
[Test]
|
|
public void TestUserWithMods()
|
|
{
|
|
setUpList();
|
|
AddStep("add user", () =>
|
|
{
|
|
MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 0,
|
|
Username = "User 0",
|
|
RulesetsStatistics = new Dictionary<string, UserStatistics>
|
|
{
|
|
{
|
|
Ruleset.Value.ShortName,
|
|
new UserStatistics { GlobalRank = RNG.Next(1, 100000), }
|
|
}
|
|
},
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
});
|
|
|
|
MultiplayerClient.ChangeUserMods(0, new Mod[]
|
|
{
|
|
new OsuModHardRock(),
|
|
new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } }
|
|
});
|
|
});
|
|
|
|
for (var i = MultiplayerUserState.Idle; i < MultiplayerUserState.Results; i++)
|
|
{
|
|
var state = i;
|
|
AddStep($"set state: {state}", () => MultiplayerClient.ChangeUserState(0, state));
|
|
}
|
|
|
|
AddStep("set state: downloading", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.Downloading(0)));
|
|
|
|
AddStep("set state: locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable()));
|
|
}
|
|
|
|
[Test]
|
|
public void TestUserWithStyle()
|
|
{
|
|
setUpList();
|
|
AddStep("add users", () =>
|
|
{
|
|
MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 0,
|
|
Username = "User 0",
|
|
RulesetsStatistics = new Dictionary<string, UserStatistics>
|
|
{
|
|
{
|
|
Ruleset.Value.ShortName,
|
|
new UserStatistics { GlobalRank = RNG.Next(1, 100000), }
|
|
}
|
|
},
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
});
|
|
|
|
MultiplayerClient.ChangeUserStyle(0, 259, 2);
|
|
});
|
|
|
|
AddStep("set beatmap locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable()));
|
|
AddStep("change user style to beatmap: 258, ruleset: 1", () => MultiplayerClient.ChangeUserStyle(0, 258, 1));
|
|
AddStep("change user style to beatmap: null, ruleset: null", () => MultiplayerClient.ChangeUserStyle(0, null, null));
|
|
}
|
|
|
|
[Test]
|
|
public void TestModOverlap()
|
|
{
|
|
setUpList();
|
|
AddStep("add dummy mods", () =>
|
|
{
|
|
MultiplayerClient.ChangeUserMods(new Mod[]
|
|
{
|
|
new OsuModNoFail(),
|
|
new OsuModDoubleTime()
|
|
});
|
|
});
|
|
|
|
AddStep("add user with mods", () =>
|
|
{
|
|
MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 0,
|
|
Username = "Baka",
|
|
RulesetsStatistics = new Dictionary<string, UserStatistics>
|
|
{
|
|
{
|
|
Ruleset.Value.ShortName,
|
|
new UserStatistics { GlobalRank = RNG.Next(1, 100000), }
|
|
}
|
|
},
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
});
|
|
MultiplayerClient.ChangeUserMods(0, new Mod[]
|
|
{
|
|
new OsuModHardRock(),
|
|
new OsuModDoubleTime()
|
|
});
|
|
});
|
|
|
|
AddStep("set 0 ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Ready));
|
|
|
|
AddStep("set 1 spectate", () => MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Spectating));
|
|
|
|
// Have to set back to idle due to status priority.
|
|
AddStep("set 0 no map, 1 ready", () =>
|
|
{
|
|
MultiplayerClient.ChangeState(MultiplayerUserState.Idle);
|
|
MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded());
|
|
MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Ready);
|
|
});
|
|
|
|
AddStep("set 0 downloading", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
|
|
|
|
AddStep("set 0 spectate", () => MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Spectating));
|
|
|
|
AddStep("make both default", () =>
|
|
{
|
|
MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable());
|
|
MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Idle);
|
|
MultiplayerClient.ChangeState(MultiplayerUserState.Idle);
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void TestModsAndRuleset()
|
|
{
|
|
setUpList();
|
|
AddStep("add another user", () =>
|
|
{
|
|
MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = 0,
|
|
Username = "User 0",
|
|
RulesetsStatistics = new Dictionary<string, UserStatistics>
|
|
{
|
|
{
|
|
Ruleset.Value.ShortName,
|
|
new UserStatistics { GlobalRank = RNG.Next(1, 100000), }
|
|
}
|
|
},
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
});
|
|
|
|
MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable());
|
|
});
|
|
|
|
AddStep("set user styles", () =>
|
|
{
|
|
MultiplayerClient.ChangeUserStyle(API.LocalUser.Value.OnlineID, 259, 1);
|
|
MultiplayerClient.ChangeUserMods(API.LocalUser.Value.OnlineID,
|
|
[new APIMod(new TaikoModConstantSpeed()), new APIMod(new TaikoModHidden()), new APIMod(new TaikoModFlashlight()), new APIMod(new TaikoModHardRock())]);
|
|
|
|
MultiplayerClient.ChangeUserStyle(0, 259, 2);
|
|
MultiplayerClient.ChangeUserMods(0,
|
|
[new APIMod(new CatchModFloatingFruits()), new APIMod(new CatchModHidden()), new APIMod(new CatchModMirror())]);
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void TestTeams()
|
|
{
|
|
setUpList();
|
|
AddStep("enable teams", () => MultiplayerClient.ChangeSettings(matchType: MatchType.TeamVersus));
|
|
AddAssert("one unique panel", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 1);
|
|
|
|
int id = 3;
|
|
AddRepeatStep("add users", () => MultiplayerClient.AddUser(new APIUser
|
|
{
|
|
Id = Interlocked.Increment(ref id),
|
|
Username = "Second",
|
|
CoverUrl = TestResources.COVER_IMAGE_3,
|
|
}), 5);
|
|
|
|
AddAssert("two unique panels", () => this.ChildrenOfType<ParticipantPanel>().Select(p => p.Current.Value).Distinct().Count() == 6);
|
|
|
|
AddAssert("user 1001 on red team",
|
|
() => (MultiplayerClient.ClientRoom!.Users.Single(u => u.UserID == 1001).MatchState as TeamVersusUserState)?.TeamID,
|
|
() => Is.EqualTo(0));
|
|
AddStep("click first team indicator", () =>
|
|
{
|
|
InputManager.MoveMouseTo(this.ChildrenOfType<TeamDisplay>().First());
|
|
InputManager.Click(MouseButton.Left);
|
|
});
|
|
AddAssert("user 1001 on blue team",
|
|
() => (MultiplayerClient.ClientRoom!.Users.Single(u => u.UserID == 1001).MatchState as TeamVersusUserState)?.TeamID,
|
|
() => Is.EqualTo(1));
|
|
}
|
|
|
|
private void createNewParticipantsList()
|
|
{
|
|
ParticipantsList? participantsList = null;
|
|
|
|
AddStep("create new list", () => Child = new OsuContextMenuContainer
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Child = participantsList = new ParticipantsList
|
|
{
|
|
Anchor = Anchor.Centre,
|
|
Origin = Anchor.Centre,
|
|
RelativeSizeAxes = Axes.Y,
|
|
Size = new Vector2(380, 0.7f)
|
|
}
|
|
});
|
|
|
|
AddUntilStep("wait for list to load", () => participantsList?.IsLoaded == true);
|
|
|
|
AddStep("set beatmap available", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()));
|
|
}
|
|
|
|
private void checkProgressBarVisibility(bool visible) =>
|
|
AddUntilStep($"progress bar {(visible ? "is" : "is not")}visible", () =>
|
|
this.ChildrenOfType<ProgressBar>().Single().IsPresent == visible);
|
|
}
|
|
}
|