fix: store embargoes as smallID numbers (drop string[] wart)

PlayerState.embargoes was string[] of stringified smallIDs — the
renderer parsed each entry with parseInt() to use as an array index.
Flagged in the integration handoff as something that should be number[].

Switch to number[] end-to-end: renderer type, relation-matrix derive
(no parseInt), PlayerView.setEmbargoSmallIDs / hasEmbargoAgainst
(numeric Array.includes, no String() temporaries), and GameView's
embargo translation pass. Also updates the PlayerView test that pinned
the old format.
This commit is contained in:
evanpelle
2026-05-16 17:45:29 -07:00
parent e87e2cd58c
commit 8955be7667
5 changed files with 14 additions and 16 deletions
@@ -67,8 +67,7 @@ export function buildRelationMatrix(
}
if (ps.embargoes) {
for (const eStr of ps.embargoes) {
const eID = parseInt(eStr, 10);
for (const eID of ps.embargoes) {
if (eID > 0 && eID < RELATION_SIZE) {
matrix[sid * RELATION_SIZE + eID] = RELATION_EMBARGO;
matrix[eID * RELATION_SIZE + sid] = RELATION_EMBARGO;
+1 -1
View File
@@ -63,7 +63,7 @@ export interface PlayerState {
hasSpawned: boolean;
lastDeleteUnitTick: number;
allies: number[];
embargoes: string[];
embargoes: number[];
targets: number[];
outgoingAttacks: AttackData[];
incomingAttacks: AttackData[];
+3 -3
View File
@@ -342,14 +342,14 @@ export class GameView implements GameMap {
gu.updates[GameUpdateType.Player].forEach((pu) => {
const player = this._players.get(pu.id);
if (player === undefined) return;
const smallIDStrings: string[] = [];
const smallIDs: number[] = [];
for (const otherPlayerID of pu.embargoes) {
const otherPV = this._players.get(otherPlayerID);
if (otherPV !== undefined) {
smallIDStrings.push(String(otherPV.smallID()));
smallIDs.push(otherPV.smallID());
}
}
player.setEmbargoSmallIDs(smallIDStrings);
player.setEmbargoSmallIDs(smallIDs);
});
if (this._myClientID) {
+6 -7
View File
@@ -64,8 +64,8 @@ function staticFromUpdate(pu: PlayerUpdate): PlayerStatic {
}
function stateFromUpdate(pu: PlayerUpdate): PlayerState {
// embargoes: Set<PlayerID strings> on the wire, but the renderer expects
// stringified smallIDs. GameView fills these in via setEmbargoes() because
// embargoes: Set<PlayerID strings> on the wire, but the renderer stores
// smallIDs (numbers). GameView fills these in via setEmbargoes() because
// it has the PlayerID → smallID lookup table.
return {
smallID: pu.smallID,
@@ -249,9 +249,9 @@ export class PlayerView {
applyStateUpdate(this.state, pu);
}
/** Set the renderer-format embargoes (stringified smallIDs). */
setEmbargoSmallIDs(smallIDStrings: string[]): void {
this.state.embargoes = smallIDStrings;
/** Set the renderer-format embargoes (smallIDs). */
setEmbargoSmallIDs(smallIDs: number[]): void {
this.state.embargoes = smallIDs;
}
territoryColor(tile?: TileRef): Colord {
@@ -493,8 +493,7 @@ export class PlayerView {
}
hasEmbargoAgainst(other: PlayerView): boolean {
const otherSmallIDStr = String(other.smallID());
return this.state.embargoes.includes(otherSmallIDStr);
return this.state.embargoes.includes(other.smallID());
}
hasEmbargo(other: PlayerView): boolean {
+3 -3
View File
@@ -152,8 +152,8 @@ describe("PlayerView relations", () => {
aTeam?: string;
bTeam?: string;
// Embargoes are renderer-format: stringified smallIDs of the OTHER player.
aEmbargoSmallIDs?: string[];
bEmbargoSmallIDs?: string[];
aEmbargoSmallIDs?: number[];
bEmbargoSmallIDs?: number[];
aOutgoingReq?: string[];
} = {},
) {
@@ -207,7 +207,7 @@ describe("PlayerView relations", () => {
it("hasEmbargoAgainst / hasEmbargo are symmetric on the second", () => {
// a embargoes b — by smallID (renderer format)
const aEmbargoesB = pair(1, 2, { aEmbargoSmallIDs: ["2"] });
const aEmbargoesB = pair(1, 2, { aEmbargoSmallIDs: [2] });
// One-way directional embargo from a
expect(aEmbargoesB.a.hasEmbargoAgainst(aEmbargoesB.b)).toBe(true);
expect(aEmbargoesB.b.hasEmbargoAgainst(aEmbargoesB.a)).toBe(false);