[BUGFIX] allow users to update username pre-game (#3298)

## Description:

Fix player rename in pre-game lobby on rejoin

Previously, when a player left a lobby, changed their name, and
rejoined, the server reused the original Client object without updating
the username. Now rejoinClient accepts the new username and applies it
if the game hasn't started yet, while still preserving names mid-game
for consistency.


## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

w.o.n
This commit is contained in:
Ryan
2026-02-28 22:22:10 +00:00
committed by GitHub
parent 5542ac12e1
commit aa451e217f
4 changed files with 25 additions and 9 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ export class Client {
public readonly roles: string[] | undefined,
public readonly flares: string[] | undefined,
public readonly ip: string,
public readonly username: string,
public username: string,
public readonly uncensoredUsername: string,
public ws: WebSocket,
public readonly cosmetics: PlayerCosmetics | undefined,
+2 -1
View File
@@ -46,10 +46,11 @@ export class GameManager {
persistentID: string,
gameID: GameID,
lastTurn: number = 0,
newUsername?: string,
): boolean {
const game = this.games.get(gameID);
if (!game) return false;
return game.rejoinClient(ws, persistentID, lastTurn);
return game.rejoinClient(ws, persistentID, lastTurn, newUsername);
}
createGame(
+8
View File
@@ -257,10 +257,13 @@ export class GameServer {
// Attempt to reconnect a client by persistentID. Returns true if successful.
// Only the WebSocket is updated — username, cosmetics, etc. are preserved
// from the original join to maintain consistency throughout the game session.
// Exception: in the pre-game lobby, the username is updated so players can
// rename between leaving and rejoining.
public rejoinClient(
ws: WebSocket,
persistentID: string,
lastTurn: number = 0,
newUsername?: string,
): boolean {
const clientID = this.getClientIdForPersistentId(persistentID);
if (!clientID) return false;
@@ -283,6 +286,11 @@ export class GameServer {
client.lastPing = Date.now();
this.markClientDisconnected(client.clientID, false);
// Allow username updates in the pre-game lobby
if (!this._hasStarted && newUsername !== undefined) {
client.username = newUsername;
}
client.ws = ws;
this.addListeners(client);
this.startLobbyInfoBroadcast();
+14 -7
View File
@@ -356,8 +356,20 @@ export async function startWorker() {
}
// Try to reconnect an existing client (e.g., page refresh)
// If successful, skip all authorization
if (gm.rejoinClient(ws, persistentId, clientMsg.gameID)) {
// If successful, skip all authorization (but pass updated username
// so players can rename in the pre-game lobby)
const censoredUsername = privilegeRefresher
.get()
.censorUsername(clientMsg.username);
if (
gm.rejoinClient(
ws,
persistentId,
clientMsg.gameID,
0,
censoredUsername,
)
) {
return;
}
@@ -439,11 +451,6 @@ export async function startWorker() {
}
}
// Censor profane usernames server-side (don't reject, just rename)
const censoredUsername = privilegeRefresher
.get()
.censorUsername(clientMsg.username);
// Create client and add to game
const client = new Client(
generateID(),