clientId replay bugfix (was picking first clientID in the array) (#3369)

## Description:

clientId replay bugfix (was picking first clientID in the array)

https://discord.com/channels/1359946986937258015/1479543573404844042

## 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-03-06 21:58:10 +00:00
committed by GitHub
parent 5594109641
commit 0eb23c0c8c
8 changed files with 22 additions and 14 deletions
+7 -3
View File
@@ -194,7 +194,7 @@ export function joinLobby(
async function createClientGame(
lobbyConfig: LobbyConfig,
clientID: ClientID,
clientID: ClientID | undefined,
eventBus: EventBus,
transport: Transport,
userSettings: UserSettings,
@@ -267,7 +267,7 @@ export class ClientGameRunner {
constructor(
private lobby: LobbyConfig,
private clientID: ClientID,
private clientID: ClientID | undefined,
private eventBus: EventBus,
private renderer: GameRenderer,
private input: InputHandler,
@@ -294,7 +294,7 @@ export class ClientGameRunner {
}
private async saveGame(update: WinUpdate) {
if (this.myPlayer === null) {
if (!this.clientID) {
return;
}
const players: PlayerRecord[] = [
@@ -544,6 +544,7 @@ export class ClientGameRunner {
return;
}
if (this.myPlayer === null) {
if (!this.clientID) return;
const myPlayer = this.gameView.playerByClientID(this.clientID);
if (myPlayer === null) return;
this.myPlayer = myPlayer;
@@ -578,6 +579,7 @@ export class ClientGameRunner {
const tile = this.gameView.ref(cell.x, cell.y);
if (this.myPlayer === null) {
if (!this.clientID) return;
const myPlayer = this.gameView.playerByClientID(this.clientID);
if (myPlayer === null) return;
this.myPlayer = myPlayer;
@@ -639,6 +641,7 @@ export class ClientGameRunner {
}
if (this.myPlayer === null) {
if (!this.clientID) return;
const myPlayer = this.gameView.playerByClientID(this.clientID);
if (myPlayer === null) return;
this.myPlayer = myPlayer;
@@ -664,6 +667,7 @@ export class ClientGameRunner {
}
if (this.myPlayer === null) {
if (!this.clientID) return;
const myPlayer = this.gameView.playerByClientID(this.clientID);
if (myPlayer === null) return;
this.myPlayer = myPlayer;
+3 -2
View File
@@ -113,7 +113,8 @@ export class LocalServer {
gameStartInfo: this.lobbyConfig.gameStartInfo,
turns: [],
lobbyCreatedAt: this.lobbyConfig.gameStartInfo.lobbyCreatedAt,
myClientID: this.clientID,
// Don't send myClientID for replays — viewer has no player identity.
myClientID: this.lobbyConfig.gameRecord ? undefined : this.clientID,
} satisfies ServerStartGameMessage);
}
@@ -127,7 +128,7 @@ export class LocalServer {
gameStartInfo: this.lobbyConfig.gameStartInfo!,
turns: this.turns,
lobbyCreatedAt: this.lobbyConfig.gameStartInfo!.lobbyCreatedAt,
myClientID: this.clientID,
myClientID: this.lobbyConfig.gameRecord ? undefined : this.clientID,
} satisfies ServerStartGameMessage);
}
if (clientMsg.type === "intent") {
+1 -1
View File
@@ -33,7 +33,7 @@ import { simpleHash } from "./Util";
export async function createGameRunner(
gameStart: GameStartInfo,
clientID: ClientID,
clientID: ClientID | undefined,
mapLoader: GameMapLoader,
callBack: (gu: GameUpdateViewData | ErrorUpdate) => void,
): Promise<GameRunner> {
+3 -2
View File
@@ -552,8 +552,9 @@ export const ServerStartGameMessageSchema = z.object({
turns: TurnSchema.array(),
gameStartInfo: GameStartInfoSchema,
lobbyCreatedAt: z.number(),
// The clientID assigned to this connection by the server
myClientID: ID,
// The clientID assigned to this connection by the server.
// Absent for replays where the viewer has no player identity.
myClientID: ID.optional(),
});
export const ServerDesyncSchema = z.object({
+1 -1
View File
@@ -36,7 +36,7 @@ export class Executor {
constructor(
private mg: Game,
private gameID: GameID,
private clientID: ClientID,
private clientID: ClientID | undefined,
) {
// Add one to avoid id collisions with bots.
this.random = new PseudoRandom(simpleHash(gameID) + 1);
+5 -3
View File
@@ -657,7 +657,7 @@ export class GameView implements GameMap {
public worker: WorkerClient,
private _config: Config,
private _mapData: TerrainMapData,
private _myClientID: ClientID,
private _myClientID: ClientID | undefined,
private _myUsername: string,
private _gameID: GameID,
private humans: Player[],
@@ -785,7 +785,9 @@ export class GameView implements GameMap {
}
});
this._myPlayer ??= this.playerByClientID(this._myClientID);
if (this._myClientID) {
this._myPlayer ??= this.playerByClientID(this._myClientID);
}
for (const unit of this._units.values()) {
unit._wasUpdated = false;
@@ -1103,7 +1105,7 @@ export class GameView implements GameMap {
);
}
myClientID(): ClientID {
myClientID(): ClientID | undefined {
return this._myClientID;
}
+1 -1
View File
@@ -23,7 +23,7 @@ export class WorkerClient {
constructor(
private gameStartInfo: GameStartInfo,
private clientID: ClientID,
private clientID: ClientID | undefined,
) {
this.worker = new Worker(new URL("./Worker.worker.ts", import.meta.url), {
type: "module",
+1 -1
View File
@@ -39,7 +39,7 @@ interface BaseWorkerMessage {
export interface InitMessage extends BaseWorkerMessage {
type: "init";
gameStartInfo: GameStartInfo;
clientID: ClientID;
clientID: ClientID | undefined;
}
export interface TurnMessage extends BaseWorkerMessage {