perf(core): speed up packedTileUpdates (Uint32 pairs, no tile wrappers) (#3255)

## Description
Reduces CPU + GC pressure from tile update serialization.

**What changed**
- Switched `packedTileUpdates` from `BigUint64Array` (BigInt packing) to
`Uint32Array` `[tileRef, state]` pairs, updating `GameView` ingestion.
- Updated tile state to use `GameMap.tileState(tile)` and
`GameMap.updateTile(tile, state)`.
- Removed per-tile `GameUpdateType.Tile` wrapper allocations by
recording raw `(tile, state)` pairs in `GameImpl` and draining them via
`drainPackedTileUpdates()` in `GameRunner`.

**Why it’s faster**
- Avoids BigInt and pack/unpack.
- Avoids per-tile object allocations.

**Compatibility**
- Wire format change: `packedTileUpdates` is now `Uint32Array` pairs
instead of `BigUint64Array`.

## Please complete the following:

- [ ] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [ ] 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:

DISCORD_USERNAME
This commit is contained in:
scamiv
2026-02-21 06:01:03 +01:00
committed by GitHub
parent 444aa16ac8
commit ea2a76609f
6 changed files with 68 additions and 63 deletions
+12 -8
View File
@@ -25,7 +25,7 @@ import {
UnitInfo,
UnitType,
} from "./Game";
import { GameMap, TileRef, TileUpdate } from "./GameMap";
import { GameMap, TileRef } from "./GameMap";
import {
AllianceView,
AttackUpdate,
@@ -648,9 +648,13 @@ export class GameView implements GameMap {
this.lastUpdate = gu;
this.updatedTiles = [];
this.lastUpdate.packedTileUpdates.forEach((tu) => {
this.updatedTiles.push(this.updateTile(tu));
});
const packed = this.lastUpdate.packedTileUpdates;
for (let i = 0; i + 1 < packed.length; i += 2) {
const tile = packed[i];
const state = packed[i + 1];
this.updateTile(tile, state);
this.updatedTiles.push(tile);
}
if (gu.updates === null) {
throw new Error("lastUpdate.updates not initialized");
@@ -949,11 +953,11 @@ export class GameView implements GameMap {
): Set<TileRef> {
return this._map.bfs(tile, filter);
}
toTileUpdate(tile: TileRef): bigint {
return this._map.toTileUpdate(tile);
tileState(tile: TileRef): number {
return this._map.tileState(tile);
}
updateTile(tu: TileUpdate): TileRef {
return this._map.updateTile(tu);
updateTile(tile: TileRef, state: number): void {
this._map.updateTile(tile, state);
}
numTilesWithFallout(): number {
return this._map.numTilesWithFallout();