Skip to content

Commit 71356a9

Browse files
author
Bartłomiej Dach
authored
Use placeholder user models in ranked play if online lookups fail (ppy#37455)
Suboptimal? Sure. But the primary goal is not to crash. Crashing is a failure of the game programmer. Better can be done later. Remedies/fixes ppy#37421.
1 parent 553c203 commit 71356a9

6 files changed

Lines changed: 57 additions & 11 deletions

File tree

osu.Game.Tests/Visual/RankedPlay/TestSceneRankedPlayScreen.cs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,35 @@ public override void SetUpSteps()
2626

2727
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
2828
WaitForJoined();
29+
}
2930

31+
[Test]
32+
public void TestIntroStage()
33+
{
3034
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
3135

3236
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
37+
38+
AddStep("set round warmup phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.RoundWarmup, s => s.StarRating = 6.3f).WaitSafely());
3339
}
3440

3541
[Test]
36-
public void TestIntroStage()
42+
public void TestUnresolvedUser()
3743
{
44+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = TestUserLookupCache.UNRESOLVED_USER_ID }));
45+
46+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
47+
3848
AddStep("set round warmup phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.RoundWarmup, s => s.StarRating = 6.3f).WaitSafely());
3949
}
4050

4151
[Test]
4252
public void TestDiscardCardsStage()
4353
{
54+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
55+
56+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
57+
4458
AddStep("set discard phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
4559

4660
AddWaitStep("wait", 3);
@@ -72,6 +86,10 @@ public void TestDiscardCardsStage()
7286
[Test]
7387
public void TestAddRemoveCards()
7488
{
89+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
90+
91+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
92+
7593
AddStep("set discard phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
7694

7795
for (int i = 0; i < 3; i++)
@@ -84,6 +102,10 @@ public void TestAddRemoveCards()
84102
[Test]
85103
public void TestRevealCards()
86104
{
105+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
106+
107+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
108+
87109
var requestHandler = new BeatmapRequestHandler();
88110

89111
AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
@@ -104,6 +126,10 @@ public void TestRevealCards()
104126
[Test]
105127
public void TestPlayCardDirect()
106128
{
129+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
130+
131+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
132+
107133
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = API.LocalUser.Value.OnlineID).WaitSafely());
108134
AddWaitStep("wait", 3);
109135
AddStep("play card", () => MultiplayerClient.PlayCard(hand => hand[0]).WaitSafely());
@@ -112,6 +138,10 @@ public void TestPlayCardDirect()
112138
[Test]
113139
public void TestDiscardCardsDirect()
114140
{
141+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
142+
143+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
144+
115145
AddStep("set discard phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
116146
AddWaitStep("wait", 3);
117147
AddStep("discard cards", () => MultiplayerClient.DiscardCards(hand => hand.Take(3)).WaitSafely());
@@ -122,6 +152,10 @@ public void TestDiscardCardsDirect()
122152
[Test]
123153
public void TestPlayStage()
124154
{
155+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
156+
157+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
158+
125159
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = API.LocalUser.Value.OnlineID).WaitSafely());
126160
AddUntilStep("wait until cards are present", () => this.ChildrenOfType<PlayerHandOfCards.PlayerHandCard>().Count() == 5);
127161

@@ -153,6 +187,10 @@ public void TestPlayStage()
153187
[Test]
154188
public void TestOtherPlaysCard()
155189
{
190+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
191+
192+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
193+
156194
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
157195
AddWaitStep("wait", 5);
158196
AddStep("play beatmap", () => MultiplayerClient.PlayUserCard(2, hand => hand[0]).WaitSafely());
@@ -166,6 +204,10 @@ public void TestOtherPlaysCard()
166204
[Test]
167205
public void TestHealthChange()
168206
{
207+
AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 2 }));
208+
209+
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
210+
169211
AddStep("set play phase", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
170212
AddWaitStep("wait", 5);
171213
AddStep("change player 1 health", () => MultiplayerClient.RankedPlayChangeUserState(MultiplayerClient.LocalUser!.UserID, state => state.Life = 250_000).WaitSafely());

osu.Game/Online/API/Requests/Responses/APIUser.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,12 @@ private APIRankHistory rankHistory
312312
Colour = @"9c0101",
313313
};
314314

315+
public static APIUser UnknownUser(int userId) => new APIUser
316+
{
317+
Id = userId,
318+
Username = "Unknown user",
319+
};
320+
315321
public int OnlineID => Id;
316322

317323
public bool Equals(APIUser other) => this.MatchesOnlineID(other);

osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Intro/IntroScreen.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ private async Task loadUsers()
6060

6161
var users = await userLookupCache.GetUsersAsync(userIds).ConfigureAwait(false);
6262

63-
var player = users.OfType<APIUser>().First(it => it.Id == api.LocalUser.Value.Id);
64-
var opponent = users.OfType<APIUser>().First(it => it.Id != api.LocalUser.Value.Id);
63+
var player = users.OfType<APIUser>().FirstOrDefault(it => it.Id == api.LocalUser.Value.Id)
64+
?? api.LocalUser.Value;
65+
var opponent = users.OfType<APIUser>().FirstOrDefault(it => it.Id != api.LocalUser.Value.Id)
66+
?? APIUser.UnknownUser(userIds.First(id => id != api.LocalUser.Value.Id));
6567

6668
int playerRating = roomState.Users[player.Id].Rating;
6769
int opponentRating = roomState.Users[opponent.Id].Rating;

osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/RankedPlayScreen.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ protected override void LoadComplete()
193193
int localUserId = api.LocalUser.Value.OnlineID;
194194
int opponentUserId = ((RankedPlayRoomState)client.Room!.MatchState!).Users.Keys.Single(it => it != localUserId);
195195

196-
localUser = users.GetUserAsync(localUserId).GetResultSafely()!;
197-
opponentUser = users.GetUserAsync(opponentUserId).GetResultSafely()!;
196+
localUser = users.GetUserAsync(localUserId).GetResultSafely() ?? api.LocalUser.Value;
197+
opponentUser = users.GetUserAsync(opponentUserId).GetResultSafely() ?? APIUser.UnknownUser(opponentUserId);
198198

199199
AddRangeInternal([
200200
new RankedPlayCornerPiece(RankedPlayColourScheme.BLUE, Anchor.BottomLeft)

osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ private void onMatchEvent(MatchServerEvent ev)
607607
switch (ev)
608608
{
609609
case RollEvent rollEvent:
610-
var user = client.Room?.Users.SingleOrDefault(u => u.UserID == rollEvent.UserID)?.User ?? new APIUser { Username = "Unknown user" };
610+
var user = client.Room?.Users.SingleOrDefault(u => u.UserID == rollEvent.UserID)?.User ?? APIUser.UnknownUser(rollEvent.UserID);
611611
string text = $"{user.Username} rolled {"point".ToQuantity(rollEvent.Result)} out of {rollEvent.Max}.";
612612
chat.Channel.Value?.AddNewMessages(new InfoMessage(text));
613613
break;

osu.Game/Screens/Play/Leaderboards/MultiplayerLeaderboardProvider.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,7 @@ private void load(OsuConfigManager config, IAPIProvider api, CancellationToken c
8989

9090
for (int i = 0; i < lookedUpUsers.Length; i++)
9191
{
92-
var user = lookedUpUsers[i] ?? new APIUser
93-
{
94-
Id = users[i].UserID,
95-
Username = "Unknown user",
96-
};
92+
var user = lookedUpUsers[i] ?? APIUser.UnknownUser(users[i].UserID);
9793

9894
var trackedUser = UserScores[user.Id];
9995

0 commit comments

Comments
 (0)