Commit Graph

3874 Commits

Author SHA1 Message Date
Ryan Barlow e2901e72dd indentity store instead 2026-05-26 18:54:58 +01:00
Ryan Barlow fea01e63e9 rabbit 2026-05-26 18:33:27 +01:00
Ryan Barlow 1e14b88d4e rabbbit 2026-05-25 22:12:33 +01:00
Ryan Barlow b3699a9f5f getValue() now requires isValid() 2026-05-25 21:38:41 +01:00
Ryan Barlow e2be4aadce revert 2026-05-25 21:37:34 +01:00
Ryan Barlow 781c74d800 fix test 2026-05-25 21:29:56 +01:00
Ryan Barlow 8ccb0bb89b prevent opening modal 2026-05-25 21:26:56 +01:00
Ryan Barlow 442617b380 validateIdentity 2026-05-25 21:05:28 +01:00
Ryan Barlow a2926b409d await validation 2026-05-25 20:50:24 +01:00
Ryan Barlow cdc331d8ba update 2026-05-25 20:33:58 +01:00
Ryan Barlow d9fedb6eb2 restructure worker 2026-05-25 19:14:46 +01:00
Ryan Barlow edf1d03275 remove from jwt 2026-05-25 19:04:27 +01:00
Ryan Barlow 4cf234fb7a update 2026-05-25 18:58:07 +01:00
Ryan Barlow 08528b7cfa enforce clantag 2026-05-24 00:59:43 +01:00
Evan db501c68d2 Put friends on the same team (#3994)
Fixes #3911

## Description:

- Server captures `publicId` and `friends` from `getUserMe()` and
includes each player's in-game friend `clientID`s in `PlayerSchema` on
game start
- Team assignment treats friends as a **soft preference** (best-effort):
a non-clan player goes to the team where the most of their friends
already are; if that team is full they spill to the next-emptiest team
rather than getting kicked
- Clans remain strict (kick overflow) since clan membership is an
explicit opt-in; friends are implicit, so a friend-of-friend chain that
doesn't fit shouldn't bench anyone
- Friendship is symmetric — an edge from either direction counts, which
keeps things working when one side's `getUserMe` is stale
- Lobby preview unchanged — friend grouping only takes effect once the
game actually starts (avoids exposing friend lists in the lobby payload)


## 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:

evan
2026-05-23 18:02:41 +01:00
dependabot[bot] db0ec97dc4 Bump ws from 8.20.0 to 8.20.1 in the npm_and_yarn group across 1 directory (#3969)
Bumps the npm_and_yarn group with 1 update in the / directory:
[ws](https://github.com/websockets/ws).

Updates `ws` from 8.20.0 to 8.20.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/websockets/ws/releases">ws's
releases</a>.</em></p>
<blockquote>
<h2>8.20.1</h2>
<h1>Bug fixes</h1>
<ul>
<li>Fixed an uninitialized memory disclosure issue in
<code>websocket.close()</code>
(c0327ec1).</li>
</ul>
<p>Providing a <code>TypedArray</code> (e.g. <code>Float32Array</code>)
as the <code>reason</code> argument for
<code>websocket.close()</code>, rather than the supported string or
<code>Buffer</code> types, caused
uninitialized memory to be disclosed to the remote peer.</p>
<pre lang="js"><code>import { deepStrictEqual } from 'node:assert';
import { WebSocket, WebSocketServer } from 'ws';
<p>const wss = new WebSocketServer(
{ port: 0, skipUTF8Validation: true },
function () {
const { port } = wss.address();
const ws = new WebSocket(<code>ws://localhost:${port}</code>, {
skipUTF8Validation: true
});</p>
<pre><code>ws.on('close', function (code, reason) {
  deepStrictEqual(reason, Buffer.alloc(80));
});
</code></pre>
<p>}
);</p>
<p>wss.on('connection', function (ws) {
ws.close(1000, new Float32Array(20));
});
</code></pre></p>
<p>The issue was privately reported by <a
href="https://github.com/ChALkeR">Nikita Skovoroda</a>.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/websockets/ws/commit/5d9b316230ea931532a6671cc450f18c11edd02f"><code>5d9b316</code></a>
[dist] 8.20.1</li>
<li><a
href="https://github.com/websockets/ws/commit/c0327ec15a54d701eb6ccefaa8bef328cfc03086"><code>c0327ec</code></a>
[security] Fix uninitialized memory disclosure in
<code>websocket.close()</code></li>
<li><a
href="https://github.com/websockets/ws/commit/ce2a3d62437995a47e6056d485a33d21b6a8f867"><code>ce2a3d6</code></a>
[ci] Test on node 26</li>
<li><a
href="https://github.com/websockets/ws/commit/58e45b872bb0f35a3edd553c27e105300a4f5bd0"><code>58e45b8</code></a>
[ci] Do not test on node 25</li>
<li><a
href="https://github.com/websockets/ws/commit/5f26c245231a4b018479a9269e8c3da4773fe42f"><code>5f26c24</code></a>
[ci] Run the lint step on node 24</li>
<li>See full diff in <a
href="https://github.com/websockets/ws/compare/8.20.0...8.20.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ws&package-manager=npm_and_yarn&previous-version=8.20.0&new-version=8.20.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/openfrontio/OpenFrontIO/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-23 17:39:51 +01:00
RickD004 b1ec3ac70f Adds Indian Subcontinent map (#3975)
## Description:

Adds Map of the Indian Subcontinent, with indian and pakistani states
and surrounding countries, important rivers like the Ganges, Brahmaputra
and Indus, and Tibet/ theHimalayas

2M land pixels and 52 Nations (i think its fitting that India has the
most nations of a regional map, only continental maps have more)

Should be nice to boost whatever indian playerbase this game might have.
This region also doesnt have any representation aside from continental
maps

<img width="584" height="598" alt="image"
src="https://github.com/user-attachments/assets/4089049a-800b-4e37-ab34-2afc5de821e8"
/>
<img width="418" height="462" alt="image"
src="https://github.com/user-attachments/assets/a68e2424-5972-4105-86c9-0312ab095024"
/>

Elevation data from NASA DEM, already credited in CREDITS.md

No reference test is needed, the test suite automatically iterates over
all GameMapType enum values — no map is hardcoded by name in the tests

## 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:

tri.star1011
2026-05-23 17:38:03 +01:00
Evan fd6cd762e6 feat: friends panel (#3990)
## Description:

# Add Friends tab to Account modal

## Summary

- Adds a "Friends" tab to the Account modal, alongside Account / Stats /
Games.
- New `<friends-list>` Lit component covering the full friend lifecycle:
send request, accept / deny incoming, withdraw outgoing, remove friend,
paginated list with "Load more".
- New `FriendsApi.ts` wrapping `GET/POST/DELETE /friends*` endpoints
with typed error codes (`not_found` / `conflict` / `bad_request` /
`request_failed`).
- Zod schemas for the friend API responses in `core/ApiSchemas.ts`.
- Translations under a new `friends.*` block in `en.json`.

Friends and pending requests are displayed by public ID via
`copy-button`, matching the existing clan convention.


## 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:

evan
2026-05-23 16:16:16 +01:00
Vansh 545ad313e3 cleanup: drop unused disposer return from installSafariPinchZoomBlocker (#3992)
Follow-up to #3901 (cc @evanpelle).

## Description:

In the review on #3901, evanpelle pointed out that the disposer returned
by `installSafariPinchZoomBlocker` is never called at the call site in
`Main.ts`, and asked whether there's any reason to return it. There
isn't — the listeners live for the document's lifetime and the browser
releases them on teardown — so this PR drops the disposer.

### Changes

- `installSafariPinchZoomBlocker` now returns `void`. Removed the
`return () => { ... }` block and the `@returns` JSDoc line. Added a
sentence explaining why no disposer is needed.
- Tests: dropped the disposer-removal test, switched the behavior tests
to use fresh detached `<div>` elements (no document state leak across
tests), and verified the default-target = `document` case with
`vi.spyOn(document, 'addEventListener').mockImplementation(() => {})` so
no real listener actually attaches to the shared jsdom document.

Net diff: -23 lines (30 insertions, 53 deletions).

### What I tested

- `npm test` — 1245 + 65 tests pass, including the 4 surviving tests for
this helper
- `npm run build-prod` — succeeds (tsc + vite)
- `npx eslint` — clean
- `npx prettier --check` on the touched files — clean

## 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:

@vansszh
2026-05-23 14:01:51 +01:00
Ryan a14cf0edc1 Clan Game History (#3988)
## Description:

Adds 
<img width="1046" height="901" alt="image"
src="https://github.com/user-attachments/assets/930b0d27-4707-4836-b068-620346e7e3a7"
/>

continuation of infra https://github.com/openfrontio/infra/pull/345
## 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
2026-05-22 22:30:16 +01:00
evanpelle b486caa6f4 Wire view-mode toggles (alt-view + coordinate grid) via new ViewModeController
Moves the AlternateViewEvent / ToggleCoordinateGridEvent subscriptions out of
ClientGameRunner into a dedicated controller in src/client/controllers/. Also
wires ToggleCoordinateGridEvent (M keybind) — previously emitted with no
listener — so the persistent coordinate-grid toggle works. Grid + alt-view
hide names only under alt-view; M keeps names visible.
2026-05-22 18:30:18 +01:00
Evan ee04a19d3c unit price (#3989)
## Description:

# Ghost structure cost label

Renders the gold cost of the currently-selected build under the ghost
structure cursor, with color-coded affordability/placement state. Honors
the
existing `cursorCostLabel` user setting (legacy name `ghostPricePill`,
already
shipping ON by default).

## Behavior

| State | Color |
|---|---|
| Can afford + valid placement | white |
| Can afford + can't place here (port on land, overlap, …) | gray |
| Can't afford | red |

The number is formatted via `renderNumber` (project-wide convention —
`1.5K`,
`1.23M`, etc.) and rendered as MSDF text at a fixed world-space scale,
centered
under the ghost icon.

## Implementation

The cost was already plumbed end-to-end on
[`GhostPreviewData.cost`](src/client/render/types/Renderer.ts) but never
visualized. This PR:

- Extends [`GhostPreviewData`](src/client/render/types/Renderer.ts) with
`showCost` (from setting) and `canAfford` (gold
vs. cost check, computed in
[BuildPreviewController](src/client/controllers/BuildPreviewController.ts)).
- Adds a `setGhostCostLabel(...)` channel to the MSDF text pass — one
persistent,
non-animated text instance alongside the existing ephemeral popups. No
new
  pass, no new shader.
- Wires
[`Renderer.updateGhostPreview`](src/client/render/gl/Renderer.ts) to
push the label whenever a ghost is active.
- Renames `ConquestPopupPass` →
[`WorldTextPass`](src/client/render/gl/passes/WorldTextPass.ts) (and its
shader dir
`conquest-popup/` → `world-text/`) since it now handles conquest popups,
bonus popups, and the ghost cost label. Done with `git mv` so history is
  preserved.




https://github.com/user-attachments/assets/c5b21bf3-f440-4c28-9b94-843df9bf6a37





## 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:

evan
2026-05-22 17:30:15 +01:00
Evan 458d04e278 split account modal into multiple tabs (#3986)
## Description:

The account modal was getting too large, too much scrolling.


<img width="1091" height="779" alt="Screenshot 2026-05-22 at 2 23 23 PM"
src="https://github.com/user-attachments/assets/9553c80d-7d17-4cfd-8992-88bb335a972e"
/>
<img width="970" height="781" alt="Screenshot 2026-05-22 at 2 23 33 PM"
src="https://github.com/user-attachments/assets/847e70eb-57b7-440b-adb6-bb7c18ada43c"
/>
<img width="1100" height="718" alt="Screenshot 2026-05-22 at 2 23 42 PM"
src="https://github.com/user-attachments/assets/5b08d44c-743a-4245-86a3-bf62e01008e9"
/>


## 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:

evan
2026-05-22 15:12:01 +01:00
evanpelle 42feb36825 Highlight matching structures on UnitDisplay hover
Wires the existing ToggleStructureEvent (emitted on UnitDisplay button
mouseenter/leave) to view.setHighlightStructureTypes via a small
StructureHighlightController. StructurePass + StructureLevelPass already
implement the highlight visual — this just connects the two ends.
2026-05-22 13:34:12 +01:00
Evan 19beab9a70 flags (#3985)
# Dynamic flag atlas (runtime TEXTURE_2D_ARRAY)

Replaces the build-time `flag-atlas.png` with a runtime
`TEXTURE_2D_ARRAY`
populated on demand from each player's server-resolved flag URL. Layers
are
deduped by URL (every "Mercia" bot shares one slot), so the per-game
working
set is bounded by unique flags, not player count.

## Why

The store will eventually ship hundreds of custom flags fetched from the
CDN,
which can't be baked into a static atlas. Moving to a runtime array also
lets
the catalog grow without bloating the client bundle.

## Side effect (bonus)

Human players' country flags (`country:US`, etc.) now display next to
their
names in-game. The old atlas only contained nation names, so non-nation
flags
were silently dropped.

## Notes

- Cell size is fixed at 128×85; loaded images are aspect-fit and
centered.
- Layer cap is 512 (clamped to `MAX_ARRAY_TEXTURE_LAYERS`). Past the
cap,
  further flag requests render no icon.
- Mipmaps are regenerated after each layer upload.
- Recommend store pipeline caps custom flag uploads at SVG or PNG ≤
256×170,
  ≤ 50 KB (decode-time RAM and bandwidth, not VRAM).


## 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:

evan
2026-05-22 13:19:22 +01:00
Evan fe6581e3fe update webgl nuke effects (#3984)
## Description:

Reworks the visual look of nuked tiles to read uniformly green (no more
brown/black bleed-through), and moves the ember "particle" effect out of
the border passes — where it lived as a storage-sharing hack — into the
fallout system where it belongs.

## What changed visually

- **Fresh fallout**: bright uniform bloom with a hint of flickering
green particles dampened on fresh tiles, ramping up as heat decays
(`particleFreshScale` controls the fresh-tile dampening).
- **Stale fallout**: dark-green ground (was near-black charcoal), with
full-strength flickering particles in dark-green ↔ light-green.
- **Particles**: per-tile flicker is now de-synced (each tile pulses at
its own rate, 0.4×–1.6× base speed) so the eye can't lock onto a global
rhythm.
- **No more brown/black pixels** in fallout zones. Two root causes were
fixed:
- The territory pass now renders stale-nuke ground for **all** fallout
tiles, not just unowned ones — so an owned player's color can't show
through where the bloom is dim/transparent.
- The ember stamp (which fully replaced tile color with orange) is gone;
particle render is now additive and color-tuned green.

## Architecture cleanup

The ember effect was conceptually fallout-domain, but lived in
`BorderComputePass` (writing intensity into `borderTex.g`) and
`BorderStampPass` (stamping orange dots), just because the border pass
already had an RGBA8 texture with a free G channel. Two consumers read
from it (`BorderStampPass`, `FalloutLightPass`), and the per-tile
flicker math used no border data at all.

This PR relocates the math inline into the two passes that actually need
it (`FalloutBloomPass.extract.frag.glsl` and
`FalloutLightPass.fallout-light.frag.glsl`), drops the ember code from
both border passes, and renames `mapOverlay.ember*` →
`falloutBloom.particle*` so the settings live with their pass.

Side benefits:
- **Animation correctness**: the old setup only updated ember intensity
when `BorderComputePass`'s dirty flag flipped (highlight change,
relations update, etc.), so the supposed flicker was actually a frozen
snapshot between border events. The new inline path runs every frame as
intended.
- **Slightly cheaper per-frame compute**: removed a per-dirty-event
full-map writeback to `borderTex.g`; added a few cheap ALU ops (1 sin +
2 hashes) per fallout tile in shaders that were already running. Same
texture memory.

## Other small changes

- Renamed `mapOverlay.charcoal*` → `mapOverlay.staleNuke*` (charcoal was
a misnomer now that the ground is green).
- Added `staleNukeR/G/B` for the ground color (was hardcoded grey).
- `intensityHot` bumped 0.6 → 1.8 for a brighter fresh-nuke glow.
- Raised `railroad.railMinZoom` 2 → 4 and `railDetailZoom` 4 → 6 so
rails pop in later (separate small commit).

<img width="354" height="371" alt="Screenshot 2026-05-22 at 10 37 34 AM"
src="https://github.com/user-attachments/assets/03b46c45-c617-41b3-b3e4-9934f064bfe1"
/>
<img width="335" height="358" alt="Screenshot 2026-05-22 at 10 37 43 AM"
src="https://github.com/user-attachments/assets/af370b19-8f22-4694-9859-1ad52aa755a7"
/>
<img width="651" height="613" alt="Screenshot 2026-05-22 at 10 38 09 AM"
src="https://github.com/user-attachments/assets/e06e5101-8529-49f6-b29a-ce0563eb52d6"
/>


## 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:

evan
2026-05-22 11:08:26 +01:00
evanpelle a2b3db616b WebGL: re-upload structures when owner changes (capture)
The structure dirty flag missed ownership changes, so captured buildings
kept rendering in the previous owner's color until another structure
event (level/active/construction) forced a re-upload.
2026-05-22 11:07:48 +01:00
VariableVince 2ee2fb97e3 WebGL: return of factory/defence post radii, and railroad highlighting when placing city/port right on top (#3981)
## Description:

Show factory and defence post radius for ghost structure when placing
structures from build bar (unitdisplay).

Show when city/port is placed directly over existing railroad, by
highlighting the railroad green. The railroad is not highlighted when
instead a city/port nearby the ghost structure will be upgraded instead
of placing it on the railroad. This works with the existing code in
buildableUnits in PlayerImpl: it would already return an empty array []
for overlappingRailroads and for ghostRailPaths when canUpgrade is
false. So the old checks for uiState for Canvas2D in
BuildPreviewController weren't even needed per se, they followed the
same logic as buildableUnits in PlayerImpl already did.

Both changes emulate how it worked before the move to WebGL. 

- OverlappingRailroads now returns TileRefs instead of a railroad ID,
and it does so with less allocations than the previous code. It's a
determistic outcome, sorted and deduplicated. In doubt about this a bit,
because it's better also in case we ever do desync checks using this
data, but for the rendering it isn't needed per se and could be more
performant without allocations.
- Also: Cleanup obsolete Canvas2D rail highlighting state (UIState) that
was superseded by GhostPreviewData.

## 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:

tryout33
2026-05-22 10:33:09 +01:00
VariableVince ff11d6b8d1 WebGL: show status icons closer above names again and emoji on top (#3983)
## Description:

In the WebGL implementation, room was reserved for emoji icon between
the status icons and the name.. This is a regression from the HTML
NameLayer and it looks weird having that space sit there unused the
majority of the time when no emoji is shown.

Show status icons closer above names again. 

And when emoji icon is shown shortly, display it in place of the other
icons (with the HTML NameLayer it would be drawn on top of the other
icons but that could look messy and it's only for a short time anyway).

Not addressed in this PR: icon size is different from before WebGL
implementation, they seem smaller.

**BEFORE (after initial WebGL implementation):**
<img width="1007" height="577" alt="Icons too high up because room is
kept for emoji while on canvas they where stacked"
src="https://github.com/user-attachments/assets/ca6937c8-e265-467d-a8f5-1424540da1c1"
/>

**AFTER:**
<img width="816" height="538" alt="Icons closer and stacked again just
their size needs attention later on"
src="https://github.com/user-attachments/assets/8a700d23-ea82-4b61-b897-109dbd0e3a32"
/>

<img width="1878" height="758" alt="Icons closer and stacked again just
their size needs attention later on B"
src="https://github.com/user-attachments/assets/f6502ad1-8a6a-4dd8-80a1-7f0f2ed590a3"
/>

<img width="443" height="335" alt="Emoji replaces normal status icons
this was after emoji was just shown"
src="https://github.com/user-attachments/assets/a8b35385-08d1-4c00-9881-9607d880048e"
/>


## 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:

tryout33
2026-05-22 10:31:06 +01:00
evanpelle 40c23ed5dc Raise railroad zoom thresholds so rails pop in later 2026-05-21 20:33:26 +01:00
VariableVince 7acf1aebc2 Restore on webgl context loss (#3968)
## Description:

When WebGL context is lost, restore context and all elements.

In GameView, handle potentially transient undefined states during
context loss gracefully.

Test with chrome://gpucrash from another tab, then return to the game
tab to see it being restored
(This fake gpucrash only works once sometimes. Because the second time
the browser might reject the tab it thinks caused the gpu crash, access
to hardware acceleration. And after even more tries even disables it
browser-wide. A browser restart resets it in that case.)

## 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:

tryout33
2026-05-21 20:27:45 +01:00
Evan 41ef675e98 Improve Notification Panel (#3913)
Resolves #3910

## Description:

- Split the events HUD into two components: a new
**`<actionable-events>`** that owns alliance prompts (request / renew)
and a slimmed-down **`<events-display>`** for everything else.
- Reworked `<events-display>` into two visual tiers: dim/scrolling tier
2 on top (trade results, unit losses, donations, alliance status),
prominent tier 1 anchored at the bottom (inbound nukes, naval invasion,
attack requests, alliance broken, conquered player, chat). Tier 2 caps
at the 4 newest entries; events expire after 8s.
- Added a transient **+gold pip** above the gold pill in
`<control-panel>`, animated with a small fade-in. Fires for trade ships,
trains, donations, and conquest. Trade-ship and train arrivals are
removed from the events scroll since they're surfaced here instead.
- New `MessageType.NUKE_DETONATED` and a server-side emission in
`NukeExecution.detonate` — once an inbound nuke lands or gets
intercepted, the inbound warning vanishes and a "detonated" entry takes
its place.
- `displayMessage` gained optional `unitID` and `focusPlayerID` params
so events can link to a unit or a player. Unit captures and destructions
now navigate to the unit's last tile when clicked; donations navigate to
the other player.
- ActionableEvents card width matches `<events-display>`; cards persist
until the user clicks Accept/Reject/Renew/Ignore or the server-side
request timeout expires.
- Removed the in-events category filter UI and the gold-amount banner —
`<events-display>` is now a lightweight log that hides entirely when
empty.

<img width="570" height="444" alt="Screenshot 2026-05-21 at 1 42 30 PM"
src="https://github.com/user-attachments/assets/f103efb3-0e11-4b72-a11b-91ff6896177c"
/>

<img width="430" height="296" alt="Screenshot 2026-05-21 at 1 41 34 PM"
src="https://github.com/user-attachments/assets/ae58475a-b252-4aa6-9ce5-99dea7575ce3"
/>

## 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:

evan
2026-05-21 19:50:10 +01:00
VariableVince 513057a62c WebGL: show alliance request+duration icon, show ally and team mate targets too, some optimization (#3971)
## Description:

Show nuke icons during replay too (when there's no localPlayer).
Show alliance request envelope icon, and duration in alliance icon
(weren't calculated yet).
Show ally and team mates' targets too (weren't calculated yet).

Remove unnecessary allocations. Nukes loop allocated two new sets,
transitive targets was a new set and now uses predicate with fallback to
localPlayer.targets, localPlayer.allies and localPlayer.embargoes were
both put in new set instead of using .includes directly.

## 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:

tryout33
2026-05-19 18:17:26 -07:00
Evan c82b078dab Stagger territory tile rendering across frames (#3973)
relates to #893 

## Description:

Territory updates were uploaded in one shot per game tick, producing a
10 Hz tile update which looked choppy. This change drips each tick's
tile changes across the ~6 render frames between ticks so the fill flows
continuously instead of stepping.

Inside TerritoryPass, each changed tile is hashed by ref into one of N
buckets (configurable via tileDrip.bucketCount, set to 9 — gives ~50 ms
of jitter headroom over the tick period without making attacks feel
laggy). One bucket drains per render frame. The stable per-ref hash
keeps repeated updates to the same tile in arrival order, so the latest
owner always wins.

While in there, moved trail state ownership out of TerritoryPass and
into TrailPass where it belongs — the territory shader doesn't sample
trailTex, so the colocation was just code-reuse drift.

## 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:

evan
2026-05-19 17:35:25 -07:00
RickD004 6a8b6a1b2f Changes for Rebalancing the Taiwan Strait map (#3970)
## Description:

Resizes the Taiwan Strait map for v32, to rebalance it for 2 team games:

Yesterday the map was tested in a stream and it turned out to be
unbalanced due to the size difference of the landmasses:
https://youtu.be/gildSwTdd4I?t=2516

Adds Team spawnzones for 2 teams.

Also removes and adds new nations , suggested by its map creator
crunchybbbbb_59469 on Discord

## 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:

tri.star1011

Taiwan Strait map by crunchybbbbb_59469 on Discord, who i worked with in
this rebalance

---------

Co-authored-by: FloPinguin <25036848+FloPinguin@users.noreply.github.com>
2026-05-19 21:40:07 +00:00
dependabot[bot] 0ace428a41 Bump the npm_and_yarn group across 1 directory with 3 updates (#3964)
Bumps the npm_and_yarn group with 3 updates in the / directory:
[protobufjs](https://github.com/protobufjs/protobuf.js),
[@opentelemetry/exporter-logs-otlp-http](https://github.com/open-telemetry/opentelemetry-js)
and
[@opentelemetry/exporter-metrics-otlp-http](https://github.com/open-telemetry/opentelemetry-js).

Removes `protobufjs`

Updates `@opentelemetry/exporter-logs-otlp-http` from 0.216.0 to 0.218.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/open-telemetry/opentelemetry-js/releases">@​opentelemetry/exporter-logs-otlp-http's
releases</a>.</em></p>
<blockquote>
<h2>experimental/v0.218.0</h2>
<h2>0.218.0</h2>
<h3>🚀 Features</h3>
<ul>
<li>feat(otlp-transformer): replace protobufjs metrics serialization
with custom implementation <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6629">#6625</a>
<a
href="https://github.com/pichlermarc"><code>@​pichlermarc</code></a></li>
<li>feat(configuration): show all config validation errors, if there are
multiple <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6683">#6683</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>feat(sdk-node): allow startNodeSDK() without an arg <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6688">#6688</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
</ul>
<h3>🏠 Internal</h3>
<ul>
<li>refactor(sdk-logs): alias <code>LoggerProviderConfig</code> to
<code>LoggerProviderOptions</code> <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6691">#6691</a>
<a
href="https://github.com/david-luna"><code>@​david-luna</code></a></li>
<li>refactor(sdk-logs): use <code>Logger.enabled()</code> within
<code>Logger.emit()</code> implementation <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6680">#6680</a>
<a
href="https://github.com/david-luna"><code>@​david-luna</code></a></li>
</ul>
<h2>experimental/v0.217.0</h2>
<h2>0.217.0</h2>
<h3>🚀 Features</h3>
<ul>
<li>feat(otlp-transformer): replace protobufjs trace serialization with
custom implementation <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6625">#6625</a>
<a
href="https://github.com/pichlermarc"><code>@​pichlermarc</code></a></li>
<li>feat(configuration): auto-generate TypeScript types from OTel
declarative config JSON schema (stable v1.0.0) using
<code>json-schema-to-typescript</code> and <code>ajv</code> <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6533">#6533</a>
<a
href="https://github.com/MikeGoldsmith"><code>@​MikeGoldsmith</code></a></li>
<li>feat(configuration, sdk-node): <code>startNodeSDK()</code> code path
now uses <code>log_level</code> configuration to setup a
DiagConsoleLogger <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6668">#6668</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a>
<ul>
<li>Note that allowed values for <code>log_level</code> in a
configuration YAML file are <em>not</em> the same set as for
<code>OTEL_LOG_LEVEL</code>. Use <code>log_level: trace</code> to see
<em>all</em> logs (equivalent of <code>OTEL_LOG_LEVEL=ALL</code>). Use
<code>log_level: fatal</code> to effectively disable the SDK's internal
diagnostic logger (equivalent of <code>OTEL_LOG_LEVEL=NONE</code>).</li>
<li>If <code>log_level</code> is not specified, a diagnostic console
logger at &quot;info&quot; level will be setup.</li>
<li>An invalid YAML config file will now result in a noop OTel SDK.</li>
</ul>
</li>
</ul>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>fix(configuration): do not validate <code>OTEL_CONFIG_FILE</code>
value before using it for file config <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6643">#6643</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): improve how 'additionalProperties' in JSON
schema is translated to TS types <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6650">#6650</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): remove stripMinItems and preprocessNullArrays
from validation/parsing <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6657">#6657</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): improve handling of enums in generated types <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6659">#6659</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): improve the technique for removing '| null' on
types the JSON Schema <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6662">#6662</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(sampler-jaeger-remote): add missing axios dep <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6656">#6656</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(exporter-prometheus): handle malformed URLs in Prometheus
exporter request handler <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6674">#6674</a>
<a href="https://github.com/homanp"><code>@​homanp</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/06ad0eaaecbd49f5ead871325f852cc2a3454079"><code>06ad0ea</code></a>
chore: prepare next release (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6703">#6703</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/38ca257e64ebd13f5603d5539f8a48d6d9232037"><code>38ca257</code></a>
feat(otlp-transformer): replace protobufjs metrics serialization with
custom ...</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/013c60085b84351a4c1e4e4f79e3dd67c56661cd"><code>013c600</code></a>
chore: prepare next release (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6699">#6699</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/b7a0c63bde39d7916fdb73cbb3d64cf1c93282c5"><code>b7a0c63</code></a>
feat(semantic-conventions): update semantic conventions to v1.41.1 (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6695">#6695</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/774143b2c6667c6537c000ab48ea5ce998278ca0"><code>774143b</code></a>
chore(renovate): add minimumReleaseAge to config (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6697">#6697</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/e0dafe0d9fadaccf7dd8d7b02dd85531356e2ac1"><code>e0dafe0</code></a>
fix(otlp-exporter-base): remove brackets from IPv6 hostname in HTTP
transport...</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/f804c93d1d6d903036b8bf38f8c3713dbbaf0360"><code>f804c93</code></a>
chore(deps): update github/codeql-action digest to 68bde55 (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6682">#6682</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/95e48e7afcc475ded350b95b43070c54591ecbbb"><code>95e48e7</code></a>
refactor(sdk-logs): alias <code>LoggerProviderConfig</code> to
<code>LoggerProviderOptions</code> (...</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/907b627d9ada25844b0f06551ecd9bbda5c0ea4f"><code>907b627</code></a>
feat(sdk-node): allow startNodeSDK() without an arg (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6688">#6688</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/0d1526198fafe7f90078ff353103d0427e6c64d4"><code>0d15261</code></a>
docs: Add SIG meeting info and welcoming language (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6689">#6689</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/open-telemetry/opentelemetry-js/compare/experimental/v0.216.0...experimental/v0.218.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `@opentelemetry/exporter-metrics-otlp-http` from 0.216.0 to
0.218.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/open-telemetry/opentelemetry-js/releases">@​opentelemetry/exporter-metrics-otlp-http's
releases</a>.</em></p>
<blockquote>
<h2>experimental/v0.218.0</h2>
<h2>0.218.0</h2>
<h3>🚀 Features</h3>
<ul>
<li>feat(otlp-transformer): replace protobufjs metrics serialization
with custom implementation <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6629">#6625</a>
<a
href="https://github.com/pichlermarc"><code>@​pichlermarc</code></a></li>
<li>feat(configuration): show all config validation errors, if there are
multiple <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6683">#6683</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>feat(sdk-node): allow startNodeSDK() without an arg <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6688">#6688</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
</ul>
<h3>🏠 Internal</h3>
<ul>
<li>refactor(sdk-logs): alias <code>LoggerProviderConfig</code> to
<code>LoggerProviderOptions</code> <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6691">#6691</a>
<a
href="https://github.com/david-luna"><code>@​david-luna</code></a></li>
<li>refactor(sdk-logs): use <code>Logger.enabled()</code> within
<code>Logger.emit()</code> implementation <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6680">#6680</a>
<a
href="https://github.com/david-luna"><code>@​david-luna</code></a></li>
</ul>
<h2>experimental/v0.217.0</h2>
<h2>0.217.0</h2>
<h3>🚀 Features</h3>
<ul>
<li>feat(otlp-transformer): replace protobufjs trace serialization with
custom implementation <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6625">#6625</a>
<a
href="https://github.com/pichlermarc"><code>@​pichlermarc</code></a></li>
<li>feat(configuration): auto-generate TypeScript types from OTel
declarative config JSON schema (stable v1.0.0) using
<code>json-schema-to-typescript</code> and <code>ajv</code> <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6533">#6533</a>
<a
href="https://github.com/MikeGoldsmith"><code>@​MikeGoldsmith</code></a></li>
<li>feat(configuration, sdk-node): <code>startNodeSDK()</code> code path
now uses <code>log_level</code> configuration to setup a
DiagConsoleLogger <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6668">#6668</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a>
<ul>
<li>Note that allowed values for <code>log_level</code> in a
configuration YAML file are <em>not</em> the same set as for
<code>OTEL_LOG_LEVEL</code>. Use <code>log_level: trace</code> to see
<em>all</em> logs (equivalent of <code>OTEL_LOG_LEVEL=ALL</code>). Use
<code>log_level: fatal</code> to effectively disable the SDK's internal
diagnostic logger (equivalent of <code>OTEL_LOG_LEVEL=NONE</code>).</li>
<li>If <code>log_level</code> is not specified, a diagnostic console
logger at &quot;info&quot; level will be setup.</li>
<li>An invalid YAML config file will now result in a noop OTel SDK.</li>
</ul>
</li>
</ul>
<h3>🐛 Bug Fixes</h3>
<ul>
<li>fix(configuration): do not validate <code>OTEL_CONFIG_FILE</code>
value before using it for file config <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6643">#6643</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): improve how 'additionalProperties' in JSON
schema is translated to TS types <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6650">#6650</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): remove stripMinItems and preprocessNullArrays
from validation/parsing <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6657">#6657</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): improve handling of enums in generated types <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6659">#6659</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(configuration): improve the technique for removing '| null' on
types the JSON Schema <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6662">#6662</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(sampler-jaeger-remote): add missing axios dep <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6656">#6656</a>
<a href="https://github.com/trentm"><code>@​trentm</code></a></li>
<li>fix(exporter-prometheus): handle malformed URLs in Prometheus
exporter request handler <a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6674">#6674</a>
<a href="https://github.com/homanp"><code>@​homanp</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/06ad0eaaecbd49f5ead871325f852cc2a3454079"><code>06ad0ea</code></a>
chore: prepare next release (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6703">#6703</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/38ca257e64ebd13f5603d5539f8a48d6d9232037"><code>38ca257</code></a>
feat(otlp-transformer): replace protobufjs metrics serialization with
custom ...</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/013c60085b84351a4c1e4e4f79e3dd67c56661cd"><code>013c600</code></a>
chore: prepare next release (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6699">#6699</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/b7a0c63bde39d7916fdb73cbb3d64cf1c93282c5"><code>b7a0c63</code></a>
feat(semantic-conventions): update semantic conventions to v1.41.1 (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6695">#6695</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/774143b2c6667c6537c000ab48ea5ce998278ca0"><code>774143b</code></a>
chore(renovate): add minimumReleaseAge to config (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6697">#6697</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/e0dafe0d9fadaccf7dd8d7b02dd85531356e2ac1"><code>e0dafe0</code></a>
fix(otlp-exporter-base): remove brackets from IPv6 hostname in HTTP
transport...</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/f804c93d1d6d903036b8bf38f8c3713dbbaf0360"><code>f804c93</code></a>
chore(deps): update github/codeql-action digest to 68bde55 (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6682">#6682</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/95e48e7afcc475ded350b95b43070c54591ecbbb"><code>95e48e7</code></a>
refactor(sdk-logs): alias <code>LoggerProviderConfig</code> to
<code>LoggerProviderOptions</code> (...</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/907b627d9ada25844b0f06551ecd9bbda5c0ea4f"><code>907b627</code></a>
feat(sdk-node): allow startNodeSDK() without an arg (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6688">#6688</a>)</li>
<li><a
href="https://github.com/open-telemetry/opentelemetry-js/commit/0d1526198fafe7f90078ff353103d0427e6c64d4"><code>0d15261</code></a>
docs: Add SIG meeting info and welcoming language (<a
href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/6689">#6689</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/open-telemetry/opentelemetry-js/compare/experimental/v0.216.0...experimental/v0.218.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/openfrontio/OpenFrontIO/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 19:43:28 -07:00
RickD004 6591b055c3 Adds map of Venice 🛶 (#3935)
## Description:

Adds map of Venice. A relatively small map (similar land area to World)
for heavy trade and lots of boating.

Because of the very low difference of elevation of the zone, terrain is
instead used to show buildings.

Map source from OpenStreetMap, already credited in CREDITS.md

Very requested map, with 2 discord posts suggesting it with +15 upvotes
each

<img width="794" height="569" alt="image"
src="https://github.com/user-attachments/assets/ca7d44f2-cfc9-4e93-b7d4-43dbe62f74d4"
/>

## 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:

tri.star1011
2026-05-18 19:43:02 -07:00
Ryan 15ac42b4c1 streamer mode bugfix (#3953)
## Description:

fixes 
https://github.com/openfrontio/OpenFrontIO/issues/3572

streamer mode bufix


## 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
2026-05-18 19:20:29 -07:00
VariableVince a2aa7823a4 Display player flags next to their names again (#3965)
## Description:

Display flags again.

## 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:

tryout33
2026-05-18 19:19:02 -07:00
evanpelle 17e3ac4b05 make spawn glow follow the player's currently selected spawn tile
Plumb spawnTile through PlayerUpdate / PlayerState / applyStateUpdate
so the WebGL spawn overlay can read it directly. The glow was reading
nameData.x/y (territory centroid for label placement) which only
recomputes every 2 ticks and only when largestClusterBoundingBox has
been updated by PlayerExecution — both lag the player's actual spawn
click. Using spawnTile updates the same tick setSpawnTile() fires.

Also adds spawnTile to diffPlayerUpdate / applyStateUpdate so changes
after the initial full snapshot actually propagate (the recent
diff-only PlayerUpdate path silently dropped any field not enumerated
in those helpers).
2026-05-18 19:15:01 -07:00
evanpelle 0eb8578996 Fix nations not spawning in singleplayer when player picks fast
NationExecution gated its first SpawnExecution by the same
attackRate/attackTick throttle used for AI actions, so a nation
could wait up to ~100 ticks before scheduling its spawn. In
singleplayer the human's spawn ends the spawn phase immediately,
stranding any nation that hadn't yet reached its attackTick — on
the next tick its NationExecution sees inSpawnPhase()=false and
isAlive()=false (no tiles), and deactivates itself.

First spawn now fires on tick 1, gated by a one-shot flag to
avoid queuing duplicates. The attackRate cadence is preserved for
subsequent re-spawns so nations still hop locations during the
spawn phase.
2026-05-18 17:39:27 -07:00
Evan 62e15d2794 Cut worker→main bandwidth ~3.3× by switching PlayerUpdate to deltas (#3967)
## Description:

Cut worker→main bandwidth ~3.3× by switching PlayerUpdate from a full
per-tick snapshot to a field-level diff. PlayerImpl.toUpdate() now
caches the last sent update and returns only changed fields, or null if
nothing changed. The client-side applyStateUpdate() merges instead of
overwriting.

Per-tick total dropped from ~297 KB to ~89 KB; the Player bucket alone
went from 258 KB/tick to 50 KB/tick. Diff/apply logic lives in a new
GameUpdateUtils.ts module with unit tests.

## 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:

evan
2026-05-18 17:07:40 -07:00
VariableVince ed928db081 Display territory skins again (#3966)
## Description:

Display territory skins (patterns) again.

## 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:

tryout33
2026-05-18 15:48:05 -07:00
evanpelle 7863529b2c rename client/graphics → client/hud
The contents (Lit web components for in-game chat, build menu, leaderboard,
attack displays, etc.) are HUD, not graphics — the actual graphics is in
client/render/.
2026-05-18 13:07:26 -07:00
evanpelle f23789883b Merge webgl2 — full WebGL2 renderer migration
relates to #893

Replaces the canvas2D + Pixi.js map renderer with a pure WebGL2 pipeline.
Map-space visuals (terrain, names, structures, units, FX, selection
boxes, build ghosts, status icons, nuke trajectories, defense zones,
spawn glow, water-nuke terrain deltas) all render through dedicated
passes in src/client/render/gl/passes/. Controllers in
src/client/controllers/ push state directly to the WebGL view; no
relay events. Assets unified under resources/ + assetUrl(). Mode
toggle wired to the existing darkMode UserSetting (no more day/night
cycle). One input system (InputHandler + EventBus + TransformHandler).

Known regressions to address in follow-up work:

- [ ] webgl: highlight structures when hover on build menu
- [ ] webgl: custom flags, flag atlas
- [ ] webgl: territory patterns
- [ ] webgl: defense post outline
- [ ] webgl: territory expanse smoothing
2026-05-18 12:09:11 -07:00
evanpelle 1dd00f6264 push terrain deltas to the WebGL view so water nukes show
Terrain was uploaded once at game start and treated as static — water
nukes (land → water conversion) mutated the sim's terrain bytes but
the rendered terrain stayed dry.

Plumbed a delta path: TerrainPass and RailroadPass each get
applyTerrainDelta(refs, bytes), Renderer + GameView forward, and
WebGLFrameBuilder pushes each tick from gameView.recentlyUpdatedTerrainTiles().
Per-tile encoding is shared via the new encodeTerrainTile helper in
ColorUtils so the startup full-map build and the per-tile delta updates
can't drift.
2026-05-18 11:08:09 -07:00
evanpelle f7dabe6a98 add CLAUDE.md describing the WebGL renderer architecture 2026-05-18 10:07:19 -07:00
evanpelle 4936ae3d59 restore spawn-phase glow with a true breathing animation
SpawnOverlayPass had everything wired except a caller. WebGLFrameBuilder
now collects spawned human players each tick during spawn phase and
pushes their territory centroid + color through view.updateSpawnOverlay.
myPlayer reads as white so the local-player ring stands out.

Reshaped the shader animation: dropped the growing-disc effect, gave
the ring a true breath — radius scales 0.5×→1.15× while opacity pulses
35%→100% in phase. Replaced the sharp inner-edge ramp with a smooth
center-to-boundary fill so there's no hard cutoff or empty hole in
the middle. animSpeed bumped to 0.0035 (~1 breath/sec).
2026-05-18 09:43:14 -07:00
evanpelle 61f6d2fdd4 restore alt-view (space hold) toggle
InputHandler still emits AlternateViewEvent on space down/up, and the
renderer still has setAltView. The bridge between them lived in
MapInteraction's applyAltView, which got deleted with the rest of
MapInteraction — nothing was wiring the event to the view anymore.
Expose view.setAltView and have ClientGameRunner subscribe.
2026-05-18 09:10:05 -07:00
evanpelle 4cd22a9b5c rename render/ files to UpperCamelCase to match client convention
The render/ tree was the only place in the client still using kebab-case
filenames. Brings ~80 files in line with the rest of src/client/
(BuildPreviewController, TransformHandler, etc.). Directories kept as
they were (name-pass/, fx-pass/, passes/, utils/, debug/) since the
codebase already mixes those.

Two collisions surfaced and got resolved: render/types/ is a directory,
not a file, so its imports kept the lowercase form; and the sed pass
incidentally normalized core/pathfinding imports, which had to be
reverted since that file is actually lowercase on disk despite some
imports having referenced it as ./Types under macOS case-insensitive
resolution.
2026-05-17 21:21:05 -07:00