mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 10:53:31 +00:00
Fix ocean color change reverting nuke-created water to land (#4343)
## Problem Changing the ocean/water color in **Graphics settings** repaints the terrain — and any water tiles created by water nukes (land → water) snap back to their original land appearance. ## Root cause `TerrainPass` captures the `terrainBytes` buffer at construction and reuses it in two places: - `setOceanColor()` does a **full** terrain texture re-upload from `terrainBytes` when the ocean color changes. - `applyTerrainDelta()` applies live land→water nuke conversions, but only wrote to the **GPU texture** — never back into `terrainBytes`. So the CPU buffer stayed frozen at the map's original terrain. Changing the ocean color rebuilt the whole texture from that stale buffer, reverting every nuke crater to land. ## Fix Write each delta byte back into `terrainBytes` inside `applyTerrainDelta()`, so the buffer stays the live source of truth and full re-uploads reflect conversions. ```ts this.terrainBytes[ref] = bytes[i]; ``` The indexing already lines up — `terrainBytes` is indexed by linear ref (`y * mapW + x`), the same `ref` the delta loop iterates. The buffer is only otherwise read once at construction by `RailroadPass`/`TerrainPass` to seed GPU textures (which copy), so mutating it has no side effects elsewhere. ## Testing The WebGL passes have no unit-test harness (they need a live GL context), so this isn't covered by an automated test. Verified by reasoning through the data flow; can confirm in-game by nuking land into water and then changing the ocean color. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,9 @@ export class TerrainPass {
|
||||
* nuke). `bytes[i]` is the new terrain byte for `refs[i]` (parallel arrays).
|
||||
* One 1×1 texSubImage2D per ref — fine for the small bursts a single nuke
|
||||
* produces.
|
||||
*
|
||||
* Also writes back into `terrainBytes` so a later full re-upload (e.g.
|
||||
* setOceanColor) reflects these conversions instead of reverting them.
|
||||
*/
|
||||
applyTerrainDelta(refs: readonly number[], bytes: Uint8Array): void {
|
||||
if (refs.length === 0) return;
|
||||
@@ -101,6 +104,7 @@ export class TerrainPass {
|
||||
const ref = refs[i];
|
||||
const x = ref % this.mapW;
|
||||
const y = (ref - x) / this.mapW;
|
||||
this.terrainBytes[ref] = bytes[i];
|
||||
encodeTerrainTile(bytes[i], this.pixelScratch, 0, this.oceanColor);
|
||||
gl.texSubImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
|
||||
Reference in New Issue
Block a user