Commit Graph

3687 Commits

Author SHA1 Message Date
Mattia Migliorini d0bb3ac061 Merge branch 'main' into team-names 2026-04-28 07:40:55 +02:00
evanpelle fc45410ee5 Remove the ticks() % 5 gate in TerritoryLayer.spawnHighlight() so the spawn highlight redraws every frame instead of every 5th frame. 2026-04-27 22:13:23 -06:00
Patrick Plays Badly 79ac66df3c Add map los angeles (with roads) (#3708)
## Description:

Add Map - Los Angeles (With Roads)
Whats NY without LA? What is LA without its roads? Here is a larger map
where I have turned LAs road network into rivers. Nations named to areas
of the city or surrounding area. Map geo data is from OpenTopography. I
stenciled the highways from screenshots of online maps and some artistic
choice.


https://discord.com/channels/1284581928254701718/1482605671697613081/1482605671697613081
https://www.youtube.com/watch?v=6td9wiQKE9s

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

##Discord username
PlaysBadly

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
2026-04-27 22:05:17 -06:00
Evan 0c0f9c2a81 Update attack labels (#3784)
## Description:

The motivation behind this PR is to standardize colors & icons for
incoming and outgoing attacks. Outgoing attacks are always aquarious and
incoming are red. This also makes it much easier to see which attacks
are incoming vs outgoing at a glance, as previously the color changed
depending on attack effictiveness. Instead, show a small bar on the left
side that displays attack effectiveness.

<img width="498" height="456" alt="Screenshot 2026-04-27 at 12 58 53 PM"
src="https://github.com/user-attachments/assets/ea6928b3-5dfa-47fa-84d2-63e1e81ef6a4"
/>


Updates the in-game attack labels to match AttacksDisplay: a single
soldier icon recolored via CSS filters, aquarius for outgoing and
red-400 for incoming. Color is now purely directional — the previous
attacker-vs-defender comparison (and the troopAttackColor /
troopDefenceColor helpers that drove it) is gone, along with the
defenderTroops plumbing.

Also adds zoom-aware sizing via a new computeLabelScale(zoom) (full
screen size when zoomed in, linear shrink with a floor so labels never
disappear), bumps font/padding/snap-jump threshold for readability, and
moves immutable per-label DOM writes (icon src/filter, color) into
element creation so the per-tick path only updates the troop count.

Also fixes a bug where the labels kept swapping when 2 clusters where
similar size

## 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-04-27 20:53:09 -06:00
Evan 4aa726cfd8 Serve hashed assets from R2 via CDN_BASE (#3773)
## Description:

Add an optional CDN_BASE env var that prefixes hashed asset URLs from
asset-manifest.json, so the app can serve static assets from R2/CDN
instead of the app origin. The value is determined at runtime via the
EJS template (window.CDN_BASE) — empty string means "same origin,"
matching today's behavior.

A hack to load the worker bundle:

A same-origin Blob script that dynamic-import()s the cross-origin worker
module and buffers early postMessage calls until the imported module's
handler attaches, sidestepping the browser's refusal to construct a
Worker directly from a cross-origin URL.

## 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-04-27 11:27:54 -06:00
Giovanni 4aeece4aef fix: render spawn highlight on 1/5 frames instead of 4/5 (#3782)
Resolves #3590

## Description:
The spawnHighlight() function in TerritoryLayer.ts was using `=== 0` 
as the condition to return early, which caused the spawn highlight to 
render on 4 out of every 5 frames instead of the intended 1 out of 5. 
Changed `=== 0` to `!== 0` so the function skips rendering on 4/5 
frames, improving performance especially on large maps.


## 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
- [x ] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
2026-04-27 08:49:08 -06:00
FloPinguin 408d0e4862 Improve TribeExecution deleteAllStructures 🏛️ (#3777)
## Description:

`deleteAllStructures` did not check for `isMarkedForDeletion`, not very
clean. Now its clean.
Also rename to `deleteNextStructure` because its not possible to delete
more than 1 structure at a time.

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

FloPinguin
2026-04-26 19:10:27 -06:00
FloPinguin 8099b9fad7 Massive nation improvement 🤖 (#3761)
## Description:

- Hard / Impossible nations in team games auto-stop trading with all
enemies
- If there are a LOT of nations on the map (Enzo stream with 400 nation
HvN private games) they no longer start with a city, they start with eco
(port / factory) because they cannot gain much gold from bot-killing
- Impossible nations built way too many missile silos sometimes, caused
by the SAM overwhelming logic. Fixed now.
- In public HvN games with 5M starting gold, nations placed their
structures way too fast, which slowed down their expansion. And humans
could easily cause a lot of damage with one atom bomb. Now their first
structure is a SAM (on hard / impossible) and they wait between their
earlygame structure placements.
- Nations now spread out their port placements more evenly
- Nations are now able to attack much stronger enemies in team games
(They can expect donations)
- Improve performance a bit by adding more early-returns (Dont run any
nuking logic if nukes are disabled, no alliance logic if alliances are
disabled, no boating logic if transport boats are disabled, ...)
- Fix some of the "cannot send troops" messages in the console
(DonateTroopExecution)
- Nations build their first missile silo sooner, they should also build
more SAMs
- Nations spend their gold better after reaching the save-up-target
(previously they stopped nuking)
- Optimized save-up-targets for team games
- The richest impossible nation is nuking very dense players now (lot of
structure levels on a small island)

### How does a 5M gold HvN start look like now?


https://github.com/user-attachments/assets/e9da89c3-c0d4-4144-a741-3101746b16da

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

FloPinguin
2026-04-26 18:43:45 -06:00
Zixer1 c0febacb8e 2661 PR 2/3 Warship Port Healing, Docking Capacity, and Waiting Behavior (#3499)
Part of [#2661](https://github.com/openfrontio/OpenFrontIO/issues/2661)
(split into 3 PRs so they are not too large..)

## Description:

Part 2/3 of
[#2661](https://github.com/openfrontio/OpenFrontIO/issues/2661).

This PR adds port-based healing and docking behavior:
- Passive healing near friendly ports
- Active docked healing pool scaled by port level and shared across
docked ships
- Docking radius and capacity-by-port-level behavior
- Waiting behavior near full ports until a slot opens
- Auto-undock once fully healed

For the active healing, it works like `ActiveHeal = (PortLevel * 5) /
DockedShipsAtThatPort`
Ex:
1 ship at level 1 port -> +5 HP/tick
1 ship at level 2 port → +10 HP/tick
2 ships at level 3 port → +7.5 HP/tick each

Includes regression tests covering healing math and docking/waiting
behavior.

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

zixer._
2026-04-26 21:42:13 +00:00
Alex Pickett 4338d70420 flag-tweak (#3775)
## Description:
Small server-side data handling adjustment with focused archive
coverage.

## Checklist:
- [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:
apick
2026-04-26 21:30:11 +00:00
evanpelle 3815f043e1 Revert "Adjust troop loss calculations and troop limits (#3652)"
This reverts commit 98233d8bff.
2026-04-26 14:59:18 -06:00
Evan 7d67c80798 Include Vite's bundle output in the manifest (#3772)
## Description:

## Summary
Include Vite's bundle output (`vendor-*`, `index-*`, workers, CSS under
`static/assets/`) in the asset manifest so the R2 deploy upload covers
them alongside hashed source assets. Move the manifest from
`static/_assets/asset-manifest.json` to `static/asset-manifest.json`
since it now describes both trees, and update `update.sh` to extract the
whole `static/` tree.


## 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-04-25 21:46:02 -06:00
Evan a5c346bd4a upload manifest to r2 before starting container (#3767)
## Description:

It first sends the manifest to the worker to get a list of missing
files, then for each missing file it uploads them to r2 via cf worker.

This PR also has us write out the manifest in plan json instead of an
mjs file. This makes it easier for the shell script to parse

## Please complete the following:

- [x] 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:

evan
2026-04-25 21:15:49 -06:00
RickD004 32a254b375 add Baja California map 🏜️ (#3759)
## Description:

Adds map of the Baja California peninsula in Mexico. Majority of this
map is brown terrain to simulate the (Sonora) desert
Mexican and American states as NPCs. The peninsula while having little
landmass is balanced by the fact it will be very easy to pirate from it

<img width="503" height="583" alt="Captura de pantalla 2026-04-18
151337"
src="https://github.com/user-attachments/assets/b1acd93a-fbe4-4d17-95b6-5f4c86ec872f"
/>

Relief data from OpenTopography, already credited

## 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-04-25 15:27:30 -06:00
Evan 62299c9714 standardize UI colors to fit brand guidelines (#3754)
## Description:

We have brand colors:

<img width="738" height="900" alt="Screenshot 2026-04-25 at 12 52 29 PM"
src="https://github.com/user-attachments/assets/aac69e87-91f2-4c3f-9f1e-f69f48f5943e"
/>

So update the homepage & in-game UI to use those colors:

<img width="1185" height="946" alt="Screenshot 2026-04-25 at 12 51
06 PM"
src="https://github.com/user-attachments/assets/89a0b12c-2db1-43d4-9500-fcf405c0f7ff"
/>

Also updated buttons to use the o-button element

## 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-04-25 13:53:21 -06:00
dependabot[bot] ca9dc4e2e0 Bump the npm_and_yarn group across 1 directory with 2 updates (#3766)
Bumps the npm_and_yarn group with 2 updates in the / directory:
[fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser)
and [postcss](https://github.com/postcss/postcss).

Updates `fast-xml-parser` from 5.5.8 to 5.7.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/releases">fast-xml-parser's
releases</a>.</em></p>
<blockquote>
<h2>upgrade <code>@​nodable/entities</code> and FXB</h2>
<ul>
<li>Use <code>@nodable/entities</code> v2.1.0
<ul>
<li>breaking changes
<ul>
<li>single entity scan. You're not allowed to use entity value to form
another entity name.</li>
<li>you cant add numeric external entity</li>
<li>entity error message when expantion limit is crossed might
change</li>
</ul>
</li>
<li>typings are updated for new options related to process entity</li>
<li>please follow documentation of <code>@nodable/entities</code> for
more detail.</li>
<li>performance
<ul>
<li>if processEntities is false, then there should not be impact on
performance.</li>
<li>if processEntities is true, but you dont pass entity decoder
separately then performance may degrade by approx 8-10%</li>
<li>if processEntities is true, and you pass entity decoder separately
<ul>
<li>if no entity then performance should be same as before</li>
<li>if there are entities then performance should be increased from past
versions</li>
</ul>
</li>
</ul>
</li>
<li>ignoreAttributes is not required to be set to set xml version for
NCR entity value</li>
</ul>
</li>
<li>update 'fast-xml-builder' to sanitize malicious CDATA and comment's
content</li>
</ul>
<h2>use <code>@​nodable/entities</code> to replace entities</h2>
<ul>
<li>No API change</li>
<li>No change in performance for basic usage</li>
<li>No typing change</li>
<li>No config change</li>
<li>new dependency</li>
<li>breaking: error messages for entities might have been changed.</li>
<li></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.12...v5.6.0">https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.12...v5.6.0</a></p>
<h2>performance improvment, increase entity expansion default limit</h2>
<ul>
<li>increase default entity explansion limit as many projects demand for
that</li>
</ul>
<pre><code>maxEntitySize: 10000,
maxExpansionDepth: 10000,
maxTotalExpansions: Infinity,
maxExpandedLength: 100000,
maxEntityCount: 1000,
</code></pre>
<ul>
<li>performance improvement
<ul>
<li>reduce calls to toString</li>
<li>early return when entities are not present</li>
<li>prepare rawAttrsForMatcher only if user sets <code>jPath:
false</code></li>
</ul>
</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.9...v5.5.10">https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.9...v5.5.10</a></p>
<h2>fix typins and matcher instance in callbacks</h2>
<p>combine typings file to avoid configuration changes
pass readonly instance of matcher to the call backs to avoid accidental
push/pop call</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md">fast-xml-parser's
changelog</a>.</em></p>
<blockquote>
<p><!-- raw HTML omitted -->Note: If you find missing information about
particular minor version, that version must have been changed without
any functional change in this library.<!-- raw HTML omitted --></p>
<p>Note: Due to some last quick changes on v4, detail of v4.5.3 &amp;
v4.5.4 are not updated here. v4.5.4x is the last tag of v4 in github
repository. I'm extremely sorry for the confusion</p>
<p><strong>5.7.2 / 2026-04-25</strong></p>
<ul>
<li>allow numerical external entity for backward compatibility</li>
<li>fix <a
href="https://redirect.github.com/NaturalIntelligence/fast-xml-parser/issues/705">#705</a>:
attributesGroupName working with preserveOrder</li>
<li>fix <a
href="https://redirect.github.com/NaturalIntelligence/fast-xml-parser/issues/817">#817</a>:
stackoverflow when tag expression is very long</li>
</ul>
<p><strong>5.7.1 / 2026-04-20</strong></p>
<ul>
<li>fix typo in CJS typing file</li>
</ul>
<p><strong>5.7.0 / 2026-04-17</strong></p>
<ul>
<li>Use <code>@nodable/entities</code> v2.1.0
<ul>
<li>breaking changes
<ul>
<li>single entity scan. You're not allowed to user entity value to form
another entity name.</li>
<li>you cant add numeric external entity</li>
<li>entity error message when expantion limit is crossed might
change</li>
</ul>
</li>
<li>typings are updated for new options related to process entity</li>
<li>please follow documentation of <code>@nodable/entities</code> for
more detail.</li>
<li>performance
<ul>
<li>if processEntities is false, then there should not be impact on
performance.</li>
<li>if processEntities is true, but you dont pass entity decoder
separately then performance may degrade by approx 8-10%</li>
<li>if processEntities is true, and you pass entity decoder separately
<ul>
<li>if no entity then performance should be same as before</li>
<li>if there are entities then performance should be increased from past
versions</li>
</ul>
</li>
</ul>
</li>
<li>ignoreAttributes is not required to be set to set xml version for
NCR entity value</li>
</ul>
</li>
<li>update 'fast-xml-builder' to sanitize malicious CDATA and comment's
content</li>
</ul>
<p><strong>5.6.0 / 2026-04-15</strong></p>
<ul>
<li>fix: entity replacement for numeric entities</li>
<li>use <code>@​nodable/entities</code> to replace entities
<ul>
<li>this may change some error messages related to entities expansion
limit or inavlid use</li>
<li>post check would be exposed in future version</li>
</ul>
</li>
</ul>
<p><strong>5.5.12 / 2026-04-13</strong></p>
<ul>
<li>Performance Improvement: update path-expression-matcher
<ul>
<li>use proxy pattern than Proxy class</li>
</ul>
</li>
</ul>
<p><strong>5.5.11 / 2026-04-08</strong></p>
<ul>
<li>Performance Improvement
<ul>
<li>integrate ExpressionSet for stopNodes</li>
</ul>
</li>
</ul>
<p><strong>5.5.10 / 2026-04-03</strong></p>
<ul>
<li>increase default entity explansion limit as many projects demand for
that</li>
<li>performance improvement
<ul>
<li>reduce calls to toString</li>
<li>early return when entities are not present</li>
<li>prepare rawAttrsForMatcher only if user sets <code>jPath:
false</code></li>
</ul>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/0f08303189d541b08401d15a7137dc238a815fa7"><code>0f08303</code></a>
fix typo</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/f529642d760ef53bb9115ad4798af5dc77ac22c4"><code>f529642</code></a>
update to release v5.7.0</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/52a8583465d6a67ad19e86fe34714879a981c18e"><code>52a8583</code></a>
Revert &quot;improve performance of attributes reading&quot;</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/8d187f9abaf42ebdd85623a9ae942b08e8ae5d0c"><code>8d187f9</code></a>
update builder</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/e174168a72a65a8fccad2c42bde329d2167edf27"><code>e174168</code></a>
improve performance of attributes reading</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/79a8dde50cebaeeda75cc1ad5b97c328da106316"><code>79a8dde</code></a>
update docs</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/f5cd5a595f313ed7b0820cabfa82ebdaa08651f7"><code>f5cd5a5</code></a>
set xml version to decoder even if attributes are ignored</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/f44b9236f4bee07bba75f0549fe86c981b1aeeef"><code>f44b923</code></a>
remove unwanted tests</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/869ec8b3588304a3a6aa9f22e38445e06d4547c8"><code>869ec8b</code></a>
Use <code>@​nodable/entities</code> v2.1.0</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/7cb49e51cd060caecf296fbf718a98d8c044c8c5"><code>7cb49e5</code></a>
update release detail</li>
<li>Additional commits viewable in <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.8...v5.7.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `postcss` from 8.5.6 to 8.5.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/releases">postcss's
releases</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code>&lt;/style&gt;</code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@​TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's
changelog</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code>&lt;/style&gt;</code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@​TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/postcss/postcss/commit/33b9790263dc1562a46ce45d9532bd63e95b7986"><code>33b9790</code></a>
Release 8.5.10 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/536c79e4b01e58a3a56b09c3c0cf2323f4b9a28b"><code>536c79e</code></a>
Escape &lt;/style&gt; in CSS output (<a
href="https://redirect.github.com/postcss/postcss/issues/2074">#2074</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/afa96b2a139ce625c4d27973313479c7c85f39d4"><code>afa96b2</code></a>
Update dependencies (<a
href="https://redirect.github.com/postcss/postcss/issues/2073">#2073</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/effe88bb87cabdc1876e02adbdd30f392f19f40d"><code>effe88b</code></a>
Typo (<a
href="https://redirect.github.com/postcss/postcss/issues/2072">#2072</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/3ee79a2c4a11e41d52db50b444eebe38299495ad"><code>3ee79a2</code></a>
Thread model (<a
href="https://redirect.github.com/postcss/postcss/issues/2071">#2071</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/2e0683daca4dc2919211b03774f6b2d137136c01"><code>2e0683d</code></a>
Create incident response docs (<a
href="https://redirect.github.com/postcss/postcss/issues/2070">#2070</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/fe88ac29c06b7b218be32994cdc6ca1525bdf2c9"><code>fe88ac2</code></a>
Release 8.5.9 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/c551632496b87ab3f1965bfda5dc386b6c71963e"><code>c551632</code></a>
Avoid RegExp when we can use simple JS</li>
<li><a
href="https://github.com/postcss/postcss/commit/89a6b744060eb8dee743351c785a9fbe37d4525a"><code>89a6b74</code></a>
Move SECURITY.txt for docs folder to keep GitHub page cleaner</li>
<li><a
href="https://github.com/postcss/postcss/commit/6ceb8a46af9f9de821faee98f861bdf84617347b"><code>6ceb8a4</code></a>
Create SECURITY.md</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.6...8.5.10">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-04-25 11:56:59 -06:00
Zixer1 9ae6f8a378 Feat/auto copy lobby code (#3758)
Resolves #3757

## Description:

Simple patch that would remove an extra click that users have to do each
time they create a private lobby. On top of the existing button, the
game link will automatically be copied to the clipboard when clicking
"Create Lobby".


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

zixer._
2026-04-25 11:54:11 -06:00
VariableVince 3783352fc8 Fix: only run the deploy action within our repository (#3753)
## Description:

Fix: only run the deploy action within our repo. It was already meant to
do this, but the if statement had a bug.

This lead to errors in repos with a fork, because it would run but
couldn't find the needed secrets there of course.

## 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-04-25 11:52:51 -06:00
FloPinguin 8634efff00 Map playlist tweaks 🗺️ (#3765)
## Description:

Add Luna and ArchipelagoSea to the water-nukes-boosted maps set.

Bias Luna games towards 2 teams (75% chance), similar to how FourIslands
is biased towards 4 teams.

Restrict the FourIslands gold multiplier exclusion to team games only,
since the stalemate risk is team-mode-specific. Also removes the
startingGold25M exclusion that was bundled with it. Reasoning: Did some
data analysis to find the root cause.

1M starting gold games accidentally had 45 seconds of PVP immunity, but
thats not needed.

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

FloPinguin
2026-04-25 11:51:55 -06:00
FloPinguin 4ae1fa2ebe Remove small islands on compact maps with half threshold 🏝️ (#3762)
## Description:

Small-island removal previously ran only on the full-size terrain. The
compact (4x downscaled) map inherited that filtering before being
downscaled, which meant islands that survived at full size could end up
as tiny specks in the compact map.

This PR runs `removeSmallIslands` on the 4x terrain as well, with half
the threshold (15 vs 30 tiles), so very small islands are pruned in
compact maps while the full-size map is unchanged.

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

FloPinguin
2026-04-25 11:51:02 -06:00
Evan 54604c4313 Remove directory-URL branch from buildAssetUrl (#3756)
## Description:

buildAssetUrl had a middle branch that, when called with a directory-ish
path (e.g. assetUrl("maps")), would check whether any manifest entry had
that prefix and return an unhashed /_assets/<path> URL. This was wrong:

* The /_assets/ prefix implies a managed, hashed asset — but the
returned URL is neither. It won't exist on R2 after the migration.
* It defeats cache-busting, since no hash is applied.
* It encourages callers to reconstruct asset paths by hand via string
concatenation, bypassing the manifest as the single source of truth.
Renaming or reorganizing an asset directory would silently break callers
the manifest can't help locate.

## 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-04-25 09:33:46 -06:00
evanpelle f7482942a1 Fix proprietary asset serving in dev (#3662 regression)
The proprietary/ fallback middleware was registered with `return () => {}`,
which placed it after Vite's htmlFallbackMiddleware. Browser `<img>`
requests carry `*/*` in their Accept header, so htmlFallback intercepted
them and returned index.html — meaning OpenFrontLogo.svg, Favicon.svg,
etc. silently rendered as the HTML shell.

Register the middleware up front, check resources/ first so publicDir
retains precedence, and set Content-Type via mrmime so browsers actually
render the SVGs.
2026-04-24 09:21:50 -06:00
Zixer1 37079e6a05 2661 PR 1/3 Warship Retreat Core, Blue UI Signal, and Transport-First Target Priority (#3498)
Part of #2661 (split into 3 PRs so they are not too large..)

## Description:

Part 1/3 of #2661.

This PR adds warship retreat basics, a blue retreating UI state, and
updates target priority.

Added:
- Retreat state handling
- Blue visual for retreating warships
- Target priority: transport > warship > trade 
- Tests for retreat and target priority

Example video:
https://youtu.be/2hE2qeOeY48
Ship retreating:
<img width="630" height="488" alt="image"
src="https://github.com/user-attachments/assets/56d3e6d5-08af-453d-afe5-ee21dd6f3414"
/>
Ship healing:
<img width="483" height="311" alt="image"
src="https://github.com/user-attachments/assets/aeaf2239-bb81-444f-84ef-62dbcb48fddf"
/>
Back to being deployed:
<img width="585" height="358" alt="image"
src="https://github.com/user-attachments/assets/875828a2-8a24-4593-ac76-26426bb81057"
/>

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

zixer._
2026-04-24 08:26:14 -06:00
FloPinguin 66bbbc664b Colored SVG smiley icons next to nation names based on relation 😊 (#3746)
## Description:

Instead of coloring nation names based on diplomatic relation, small
inline SVG face icons are now shown next to the nation name in the
player info overlay:

- 😠 **Hostile** - red angry face (furrowed brows, downturned mouth)
- 😟 **Distrustful** - orange slightly-sad face (flat mouth)
- 😊 **Friendly** - green happy face (upturned smile)
- **Neutral** - no icon shown

<img width="509" height="80" alt="Screenshot 2026-04-23 013151"
src="https://github.com/user-attachments/assets/85dc3f29-0a84-45d1-902e-e75c6cad4a44"
/>
<img width="511" height="82" alt="Screenshot 2026-04-23 012809"
src="https://github.com/user-attachments/assets/7a37c8a3-08d0-448e-9eaa-16f254a296ad"
/>
<img width="511" height="88" alt="Screenshot 2026-04-23 012741"
src="https://github.com/user-attachments/assets/d617f8ca-2315-467a-85f5-63f769bd0341"
/>

No longer conflicts with green text color because of alliance now. 

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

FloPinguin
2026-04-24 08:09:03 -06:00
RickD004 aa70d6742a add Archipelago Sea map (#3749)
## Description:

Adds Archipelago Sea map. The island map to end all island maps.

This is a real location in Southwest Finland, famous for being the
archipelago with the most islands in the world.

This map is made for the very loud playerbase who enjoys naval maps.
This is probably the most heavy naval map we are gonna get. Given this
is a very experimental and unorthodox map like amazon or 4islands, it
has a rotation of 3 , low but still should pop in for people who prefer
island maps.


https://github.com/user-attachments/assets/19b32a4f-825b-4b82-aec3-b24c387b9cdd

## 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-04-24 08:07:48 -06:00
1brucben 98233d8bff Adjust troop loss calculations and troop limits (#3652)
## Description:

I think this fixes the stalemate issue mentioned in the previous PR
without restoring the attack loss "bug". I tried making very small
adjustments (possibly too small?) to meet the goal of very gradually
changing the feel of the game.

If stalemate is still an issue, would recommend boosting the toAdd
parameter. I think the issue is not that attack losses are too high
relative to defender, but rather that large attackers get nerfed so much
by this formula. Going up to .8 from .73 is a roughly 10% boost in troop
growth for an attacker that is 4x the size of a defender. Not sure
anyone will notice, but it adds up over game time.

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

1brucben
2026-04-23 12:05:38 -07:00
dependabot[bot] 1aaa3ba99f Bump uuid from 11.1.0 to 14.0.0 in the npm_and_yarn group across 1 directory (#3745)
Bumps the npm_and_yarn group with 1 update in the / directory:
[uuid](https://github.com/uuidjs/uuid).

Updates `uuid` from 11.1.0 to 14.0.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/uuidjs/uuid/releases">uuid's
releases</a>.</em></p>
<blockquote>
<h2>v14.0.0</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v13.0.0...v14.0.0">14.0.0</a>
(2026-04-19)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>expect <code>crypto</code> to be global everywhere (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>)</li>
<li>drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>) (<a
href="https://github.com/uuidjs/uuid/commit/dc4ddb87272ed2843faccd130bcc41d492688bd3">dc4ddb8</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>expect <code>crypto</code> to be global everywhere (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>) (<a
href="https://github.com/uuidjs/uuid/commit/f2c235f93059325fa43e1106e624b5291bb523c4">f2c235f</a>)</li>
<li>Use GITHUB_TOKEN for release-please and enable npm provenance (<a
href="https://redirect.github.com/uuidjs/uuid/issues/925">#925</a>) (<a
href="https://github.com/uuidjs/uuid/commit/ffa31383e8e4e1f0b4e22e504561272041b8738c">ffa3138</a>)</li>
</ul>
<h2>v13.0.0</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v12.0.0...v13.0.0">13.0.0</a>
(2025-09-08)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>) (<a
href="https://github.com/uuidjs/uuid/commit/bce9d72a3ae5b9a3dcd8eb21ef6d1820288a427a">bce9d72</a>)</li>
</ul>
<h2>v12.0.0</h2>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v11.1.0...v12.0.0">12.0.0</a>
(2025-09-05)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>update to typescript@5.2 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/887">#887</a>)</li>
<li>remove CommonJS support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/886">#886</a>)</li>
<li>drop node@16 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/883">#883</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add node@24 to ci matrix (<a
href="https://redirect.github.com/uuidjs/uuid/issues/879">#879</a>) (<a
href="https://github.com/uuidjs/uuid/commit/42b6178aa21a593257f0a72abacd220f0b7b8a92">42b6178</a>)</li>
<li>drop node@16 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/883">#883</a>) (<a
href="https://github.com/uuidjs/uuid/commit/0f38cf10366ab074f9328ae2021eea04d5f2e530">0f38cf1</a>)</li>
<li>remove CommonJS support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/886">#886</a>) (<a
href="https://github.com/uuidjs/uuid/commit/ae786e27265f50bcf7cead196c29f1869297c42f">ae786e2</a>)</li>
<li>update to typescript@5.2 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/887">#887</a>) (<a
href="https://github.com/uuidjs/uuid/commit/c7ee40598ed78584d81ab78dffded9fe5ff20b01">c7ee405</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md">uuid's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v13.0.0...v14.0.0">14.0.0</a>
(2026-04-19)</h2>
<h3>Security</h3>
<ul>
<li>Fixes <a
href="https://github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pq">GHSA-w5hq-g745-h8pq</a>:
<code>v3()</code>, <code>v5()</code>, and <code>v6()</code> did not
validate that writes would remain within the bounds of a caller-supplied
buffer, allowing out-of-bounds writes when an invalid
<code>offset</code> was provided. A <code>RangeError</code> is now
thrown if <code>offset &lt; 0</code> or <code>offset + 16 &gt;
buf.length</code>.</li>
</ul>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li><code>crypto</code> is now expected to be globally defined (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>)</li>
<li>drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>)</li>
<li>upgrade minimum supported TypeScript version to 5.4.3, in keeping
with the project's policy of supporting TypeScript versions released
within the last two years</li>
</ul>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v12.0.0...v13.0.0">13.0.0</a>
(2025-09-08)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>make browser exports the default (<a
href="https://redirect.github.com/uuidjs/uuid/issues/901">#901</a>) (<a
href="https://github.com/uuidjs/uuid/commit/bce9d72a3ae5b9a3dcd8eb21ef6d1820288a427a">bce9d72</a>)</li>
</ul>
<h2><a
href="https://github.com/uuidjs/uuid/compare/v11.1.0...v12.0.0">12.0.0</a>
(2025-09-05)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>update to typescript@5.2 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/887">#887</a>)</li>
<li>remove CommonJS support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/886">#886</a>)</li>
<li>drop node@16 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/883">#883</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add node@24 to ci matrix (<a
href="https://redirect.github.com/uuidjs/uuid/issues/879">#879</a>) (<a
href="https://github.com/uuidjs/uuid/commit/42b6178aa21a593257f0a72abacd220f0b7b8a92">42b6178</a>)</li>
<li>drop node@16 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/883">#883</a>) (<a
href="https://github.com/uuidjs/uuid/commit/0f38cf10366ab074f9328ae2021eea04d5f2e530">0f38cf1</a>)</li>
<li>remove CommonJS support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/886">#886</a>) (<a
href="https://github.com/uuidjs/uuid/commit/ae786e27265f50bcf7cead196c29f1869297c42f">ae786e2</a>)</li>
<li>update to typescript@5.2 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/887">#887</a>) (<a
href="https://github.com/uuidjs/uuid/commit/c7ee40598ed78584d81ab78dffded9fe5ff20b01">c7ee405</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>improve v4() performance (<a
href="https://redirect.github.com/uuidjs/uuid/issues/894">#894</a>) (<a
href="https://github.com/uuidjs/uuid/commit/5fd974c12718c8848035650b69b8948f12ace197">5fd974c</a>)</li>
<li>restore node: prefix (<a
href="https://redirect.github.com/uuidjs/uuid/issues/889">#889</a>) (<a
href="https://github.com/uuidjs/uuid/commit/e1f42a354593093ba0479f0b4047dae82d28c507">e1f42a3</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/uuidjs/uuid/commit/7c1ea087a8149b57380fc8bb7f68c3a215cb6e4b"><code>7c1ea08</code></a>
chore(main): release 14.0.0 (<a
href="https://redirect.github.com/uuidjs/uuid/issues/926">#926</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/3d2c5b0342f0fcb52a5ac681c3d47c13e7444b34"><code>3d2c5b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/f2c235f93059325fa43e1106e624b5291bb523c4"><code>f2c235f</code></a>
fix!: expect <code>crypto</code> to be global everywhere (requires
node@20+) (<a
href="https://redirect.github.com/uuidjs/uuid/issues/935">#935</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/529ef0899f5dd503d2ee90d690585d63d78bc212"><code>529ef08</code></a>
chore: upgrade TypeScript and fixup types (<a
href="https://redirect.github.com/uuidjs/uuid/issues/927">#927</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/086fd7976f11433edf9ac80be876b3ad243fe087"><code>086fd79</code></a>
chore: update dependencies (<a
href="https://redirect.github.com/uuidjs/uuid/issues/933">#933</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/dc4ddb87272ed2843faccd130bcc41d492688bd3"><code>dc4ddb8</code></a>
feat!: drop node@18 support (<a
href="https://redirect.github.com/uuidjs/uuid/issues/934">#934</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/0f1f9c9c9cedbae5a1d363d5406c5dfbabe81404"><code>0f1f9c9</code></a>
chore: switch to Biome for parsing and linting (<a
href="https://redirect.github.com/uuidjs/uuid/issues/932">#932</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/e2879e64bf125add903c1eff6e0860542c605013"><code>e2879e6</code></a>
chore: use maintained version of npm-run-all (<a
href="https://redirect.github.com/uuidjs/uuid/issues/930">#930</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/ffa31383e8e4e1f0b4e22e504561272041b8738c"><code>ffa3138</code></a>
fix: Use GITHUB_TOKEN for release-please and enable npm provenance (<a
href="https://redirect.github.com/uuidjs/uuid/issues/925">#925</a>)</li>
<li><a
href="https://github.com/uuidjs/uuid/commit/0423d49df2dc8efc300c804731d25f4d7e0fccc4"><code>0423d49</code></a>
docs: remove obsolete v1 option notes (<a
href="https://redirect.github.com/uuidjs/uuid/issues/915">#915</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/uuidjs/uuid/compare/v11.1.0...v14.0.0">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for uuid since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=uuid&package-manager=npm_and_yarn&previous-version=11.1.0&new-version=14.0.0)](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-04-23 11:39:22 -07:00
David 236f611f61 Cap RailroadLayer Maximum Texture Size (#3584)
Resolves #3582

## Description:

Almost exactly the same fix as #3574 , just to RailroadLayer instead of
StuctureLayer.

While browsers like Firefox will report their maximum texture size of
16384, going over 8192 causes extreme VRAM usage and massive FPS drops.
This issue is slightly more elusive as the RailroadLayer texture is not
rendered until the first railroad is created, meaning FPS will suddenly
drop mid-game.

This PR sets the RailroadLayer texture size to cap at 8192, while
keeping near-exact scales. The result is increased performance, reduced
VRAM Usage, (especially in larger maps), and the resolution of the
unplayable performance issues when RailroadLayer is present, with zero
noticeable degradation.

All tested on Giant World, where the issues were first spotted, but
applies to all maps.

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

Discord: @EnderBoy9217
2026-04-23 11:39:03 -07:00
Ivan Batsulin 4fd162415a Add fullscreen support: HUD button (desktop/Android) + iOS Add to Home Screen banner (#3688)
Resolves #3685

## Description:

Adds fullscreen support for both desktop and mobile:

**Desktop / Android** — a fullscreen toggle button in the in-game HUD
(right sidebar), next to the settings button. Icon switches between
expand/compress depending on current state, synced with
`fullscreenchange` event (works with F11 too). Hidden on browsers that
don't support `document.fullscreenEnabled`.

**iOS** — since Safari doesn't support the Fullscreen API, a dismissible
banner is shown on the main screen (above the lobby cards) explaining
how to add the game to the Home Screen for a fullscreen experience. The
banner includes:
- **How** button — opens a step-by-step guide modal with iOS version
detection (iOS 26+ shows updated steps for the new ··· menu location,
including the extra Share step inside the menu)
- **Later** — hides until next visit
- **Never** — permanently dismisses via localStorage
- **Click here** button styled as a speech bubble with a tail pointing
toward the Share button location (center for iOS ≤18, right for iOS 26+)

All user-facing strings are wired through `translateText()` with keys
added to `en.json`.

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

## UI changes: 
### For [Fullscreen API supported
browsers](https://caniuse.com/?search=fullscreen+api):


https://github.com/user-attachments/assets/026e6a67-d070-4a7e-897b-52396a43191e

### For safari on ios: (add to homescreen modal)

<img width="375" height="667" alt="IMG_2242"
src="https://github.com/user-attachments/assets/9d0a6454-8512-44cf-b6ed-989de3ff02bc"
/>
<img width="648" height="1292" alt="CleanShot 2026-04-22 at 11 29 27@2x"
src="https://github.com/user-attachments/assets/dba1c218-2b73-4bc0-ac7d-14962eb79327"
/>



## Please put your Discord username so you can be contacted if a bug or
regression is found:

fghjk_60845

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-23 11:38:07 -07:00
dependabot[bot] 9df0569c5e Bump @xmldom/xmldom from 0.8.12 to 0.8.13 in the npm_and_yarn group across 1 directory (#3742)
Bumps the npm_and_yarn group with 1 update in the / directory:
[@xmldom/xmldom](https://github.com/xmldom/xmldom).

Updates `@xmldom/xmldom` from 0.8.12 to 0.8.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/xmldom/xmldom/releases"><code>@​xmldom/xmldom</code>'s
releases</a>.</em></p>
<blockquote>
<h2>0.8.13</h2>
<p><a
href="https://github.com/xmldom/xmldom/compare/0.8.12...0.8.13">Commits</a></p>
<h3>Fixed</h3>
<ul>
<li>Security: <code>XMLSerializer.serializeToString()</code> (and
<code>Node.toString()</code>, <code>NodeList.toString()</code>) now
accept a <code>requireWellFormed</code> option (fourth argument, after
<code>isHtml</code> and <code>nodeFilter</code>). When <code>{
requireWellFormed: true }</code> is passed, the serializer throws
<code>InvalidStateError</code> for injection-prone node content,
preventing XML injection via attacker-controlled node data. <a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-j759-j44w-7fr8"><code>GHSA-j759-j44w-7fr8</code></a>
<a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-x6wf-f3px-wcqx"><code>GHSA-x6wf-f3px-wcqx</code></a>
<a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-f6ww-3ggp-fr8h"><code>GHSA-f6ww-3ggp-fr8h</code></a>
<ul>
<li>Comment: throws when <code>data</code> contains
<code>--&gt;</code></li>
<li>ProcessingInstruction: throws when <code>data</code> contains
<code>?&gt;</code></li>
<li>DocumentType: throws when <code>publicId</code> fails
<code>PubidLiteral</code>, <code>systemId</code> fails
<code>SystemLiteral</code>, or <code>internalSubset</code> contains
<code>]&gt;</code></li>
</ul>
</li>
<li>Security: DOM traversal operations
(<code>XMLSerializer.serializeToString()</code>,
<code>Node.prototype.normalize()</code>,
<code>Node.prototype.cloneNode(true)</code>,
<code>Document.prototype.importNode(node, true)</code>,
<code>node.textContent</code> getter,
<code>getElementsByTagName()</code> /
<code>getElementsByTagNameNS()</code> /
<code>getElementsByClassName()</code> / <code>getElementById()</code>)
are now iterative. Previously, deeply nested DOM trees would exhaust the
JavaScript call stack and throw an unrecoverable
<code>RangeError</code>. <a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-2v35-w6hq-6mfw"><code>GHSA-2v35-w6hq-6mfw</code></a></li>
</ul>
<p>Thank you,
<a href="https://github.com/Jvr2022"><code>@​Jvr2022</code></a>,
<a href="https://github.com/praveen-kv"><code>@​praveen-kv</code></a>,
<a href="https://github.com/TharVid"><code>@​TharVid</code></a>,
<a href="https://github.com/decsecre583"><code>@​decsecre583</code></a>,
<a href="https://github.com/tlsbollei"><code>@​tlsbollei</code></a>,
<a
href="https://github.com/KarimTantawey"><code>@​KarimTantawey</code></a>,
for your contributions</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md"><code>@​xmldom/xmldom</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/xmldom/xmldom/compare/0.8.12...0.8.13">0.8.13</a></h2>
<h3>Fixed</h3>
<ul>
<li>Security: <code>XMLSerializer.serializeToString()</code> (and
<code>Node.toString()</code>, <code>NodeList.toString()</code>) now
accept a <code>requireWellFormed</code> option (fourth argument, after
<code>isHtml</code> and <code>nodeFilter</code>). When <code>{
requireWellFormed: true }</code> is passed, the serializer throws
<code>InvalidStateError</code> for injection-prone node content,
preventing XML injection via attacker-controlled node data. <a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-j759-j44w-7fr8"><code>GHSA-j759-j44w-7fr8</code></a>
<a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-x6wf-f3px-wcqx"><code>GHSA-x6wf-f3px-wcqx</code></a>
<a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-f6ww-3ggp-fr8h"><code>GHSA-f6ww-3ggp-fr8h</code></a>
<ul>
<li>Comment: throws when <code>data</code> contains
<code>--&gt;</code></li>
<li>ProcessingInstruction: throws when <code>data</code> contains
<code>?&gt;</code></li>
<li>DocumentType: throws when <code>publicId</code> fails
<code>PubidLiteral</code>, <code>systemId</code> fails
<code>SystemLiteral</code>, or <code>internalSubset</code> contains
<code>]&gt;</code></li>
</ul>
</li>
<li>Security: DOM traversal operations
(<code>XMLSerializer.serializeToString()</code>,
<code>Node.prototype.normalize()</code>,
<code>Node.prototype.cloneNode(true)</code>,
<code>Document.prototype.importNode(node, true)</code>,
<code>node.textContent</code> getter,
<code>getElementsByTagName()</code> /
<code>getElementsByTagNameNS()</code> /
<code>getElementsByClassName()</code> / <code>getElementById()</code>)
are now iterative. Previously, deeply nested DOM trees would exhaust the
JavaScript call stack and throw an unrecoverable
<code>RangeError</code>. <a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-2v35-w6hq-6mfw"><code>GHSA-2v35-w6hq-6mfw</code></a></li>
</ul>
<p>Thank you,
<a href="https://github.com/Jvr2022"><code>@​Jvr2022</code></a>,
<a href="https://github.com/praveen-kv"><code>@​praveen-kv</code></a>,
<a href="https://github.com/TharVid"><code>@​TharVid</code></a>,
<a href="https://github.com/decsecre583"><code>@​decsecre583</code></a>,
<a href="https://github.com/tlsbollei"><code>@​tlsbollei</code></a>,
<a
href="https://github.com/KarimTantawey"><code>@​KarimTantawey</code></a>,
for your contributions</p>
<h2><a
href="https://github.com/xmldom/xmldom/compare/0.9.8...0.9.9">0.9.9</a></h2>
<h3>Added</h3>
<ul>
<li>implement <code>ParentNode.children</code> getter <a
href="https://redirect.github.com/xmldom/xmldom/pull/960"><code>[#960](https://github.com/xmldom/xmldom/issues/960)</code></a>
/ <a
href="https://redirect.github.com/xmldom/xmldom/issues/410"><code>[#410](https://github.com/xmldom/xmldom/issues/410)</code></a></li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Security: <code>createCDATASection</code> now throws
<code>InvalidCharacterError</code> when <code>data</code> contains
<code>&quot;]]&gt;&quot;</code>, as required by the <a
href="https://dom.spec.whatwg.org/#dom-document-createcdatasection">WHATWG
DOM spec</a>. <a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-wh4c-j3r5-mjhp"><code>GHSA-wh4c-j3r5-mjhp</code></a></li>
<li>Security: <code>XMLSerializer</code> now splits CDATASection nodes
whose data contains <code>&quot;]]&gt;&quot;</code> into adjacent CDATA
sections at serialization time, preventing XML injection via mutation
methods (<code>appendData</code>, <code>replaceData</code>, <code>.data
=</code>, <code>.textContent =</code>). <a
href="https://github.com/xmldom/xmldom/security/advisories/GHSA-wh4c-j3r5-mjhp"><code>GHSA-wh4c-j3r5-mjhp</code></a></li>
<li>correctly traverse ancestor chain in <code>Node.contains</code> <a
href="https://redirect.github.com/xmldom/xmldom/pull/931"><code>[#931](https://github.com/xmldom/xmldom/issues/931)</code></a></li>
</ul>
<p>Code that passes a string containing <code>&quot;]]&gt;&quot;</code>
to <code>createCDATASection</code> and relied on the previously unsafe
behavior will now receive <code>InvalidCharacterError</code>. Use a
mutation method such as <code>appendData</code> if you intentionally
need <code>&quot;]]&gt;&quot;</code> in a CDATASection node's data.</p>
<h3>Chore</h3>
<ul>
<li>updated dependencies</li>
</ul>
<p>Thank you,
<a
href="https://github.com/stevenobiajulu"><code>@​stevenobiajulu</code></a>,
<a href="https://github.com/yoshi389111"><code>@​yoshi389111</code></a>,
<a
href="https://github.com/thesmartshadow"><code>@​thesmartshadow</code></a>,
for your contributions</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/xmldom/xmldom/commit/e5c14802592685bb872c042c54c3f73758875c85"><code>e5c1480</code></a>
0.8.13</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/9611e20d75f059dc377f806a8f7ee7d1eaeaeb7c"><code>9611e20</code></a>
style: drop unused import in test file</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/dc4dff3d1d0b5a6b97c52fcc1823a735b8821e62"><code>dc4dff3</code></a>
docs: add 0.8.13 changelog entry</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/842fa38deedd2d9a9c90d0ad54aa1be75d2a41bc"><code>842fa38</code></a>
fix: prevent stack overflow in normalize (GHSA-2v35-w6hq-6mfw)</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/aeff69f5a32e8c1bd540683da9e10718f84f595c"><code>aeff69f</code></a>
test: add normalize behavioral coverage to node.test.js</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/cbdb0d7db8ae70760bd4cc181cb8f30bb0cd9d88"><code>cbdb0d7</code></a>
fix: make walkDOM iterative to prevent stack overflow
(GHSA-2v35-w6hq-6mfw)</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/0b543d31794dc198c86a0358574cb5dec29674c5"><code>0b543d3</code></a>
test: assert namespace declarations are isolated between siblings in
serializ...</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/c007c51909587990c962cf3d5c2acadf4c897b87"><code>c007c51</code></a>
refactor: migrate serializeToString to walkDOM</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/2bb3899074820089d9e76ce28a5edfdacf425025"><code>2bb3899</code></a>
test: add serializeToString coverage for uncovered branches</li>
<li><a
href="https://github.com/xmldom/xmldom/commit/e69f38d0a58731152d300e8c8eb29506f5f488fe"><code>e69f38d</code></a>
refactor: migrate importNode to walkDOM</li>
<li>Additional commits viewable in <a
href="https://github.com/xmldom/xmldom/compare/0.8.12...0.8.13">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~karfau">karfau</a>, a new releaser for
<code>@​xmldom/xmldom</code> since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@xmldom/xmldom&package-manager=npm_and_yarn&previous-version=0.8.12&new-version=0.8.13)](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-04-23 10:01:35 -07:00
RickD004 ec6e14051a Add an Antarctica map 🐧 (#3740)
## Description:

(re-submission of older PR because the old one had too many merge
conflicts)

Re-adds and reworks the previously April Fools "Reglaciated Antarctica"
as a new map, this time with proper elevation data: Map of Antarctica
centered in the South Pole.

The "appeal" of this a map is that it has no green terrain. (As such it
has a really low rotation number (of 1). )

This also completes the Continental map category (antarctica was the
only continent out of the traditional 7 missing).


https://github.com/user-attachments/assets/28302464-c533-483e-8a1b-2699093921ff

The base map image is a composite of 2 relief maps from 2 different
sources, both properly credited

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

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2026-04-22 16:04:56 -07:00
FloPinguin f7716c7d42 Little Console Cleanup 🧹 (#3741)
## Description:

Fixes these console warnings from bots:

<img width="591" height="94" alt="Screenshot 2026-04-19 033624"
src="https://github.com/user-attachments/assets/6ee79302-e2a7-4195-94e5-c1f455eb1799"
/>

Removes some spammy logs, they dont seem to be helpful?

<img width="271" height="174" alt="Screenshot 2026-04-19 033739"
src="https://github.com/user-attachments/assets/70122506-e8fb-4a72-b73e-08e72fe222bd"
/>



<img width="284" height="656" alt="Screenshot 2026-04-19 033646"
src="https://github.com/user-attachments/assets/4b4ebef2-e191-4947-9615-0e26cd9bf075"
/>

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

FloPinguin
2026-04-22 15:59:42 -07:00
Cameron Clark ad2be09ee9 Fix: Normalize sound effect loudness (#3738)
## Summary
- Normalises all 20 SFX files to -22 LUFS with true peak ≤ -2 dBFS
- Collapses a ~20dB loudness spread (hydrogen-hit at -14.94 LUFS vs
sam-hit at -34.56 LUFS) into ~2dB
- Previously jarring hits (hydrogen, atom, MIRV) pulled down 6–8dB;
previously-quiet hits (sam-hit, message) brought up to match
- Short clips (`click.mp3`, `ka-ching.mp3`) too short for EBU R128 — got
a flat -6dB trim

## Why
Addresses #3728, specifically the "*WAY too loud*" feedback. Loudest
clips were peaking within ~1.5dB of clipping.

Does **not** change overlap/stacking — per discussion in #3728 and
#3394, the 8-concurrent-sound channel limit is retained intentionally.
At -22 LUFS, multiple overlapping events remain comfortable.

## Before / after (key files)

| Effect | Before (LUFS / TP dBFS) | After (LUFS / TP dBFS) | Δ |
|---|---|---|---|
| hydrogen-hit | -14.94 / -1.62 | -22.52 / -9.10 | −7.6 dB |
| atom-launch | -17.16 / -1.53 | -23.84 / -8.14 | −6.7 dB |
| hydrogen-launch | -16.15 / -1.92 | -23.65 / -9.37 | −7.5 dB |
| mirv-launch | -19.08 / -3.17 | -24.80 / -9.80 | −5.7 dB |
| sam-hit | -34.56 / -10.77 | -23.97 / -1.98 | +10.6 dB (raised up) |
| message | -29.47 / -24.46 | -21.97 / -17.00 | +7.5 dB (raised up) |

All durations unchanged (verified with `ffprobe`). All true peaks stay
below -1 dBFS — no clipping.

## How
Applied with ffmpeg's EBU R128 `loudnorm` filter:
```
ffmpeg -i in.mp3 -af "loudnorm=I=-22:TP=-2:LRA=7" -codec:a libmp3lame -q:a 2 out.mp3
```

Files shorter than the 1-second EBU R128 window (`click.mp3` 153ms,
`ka-ching.mp3` 586ms) used \`-af volume=-6dB\` instead.

## Test plan
- [x] Singleplayer: launch atom / hydrogen / MIRV nukes, verify
detonations are satisfying but not startling
- [x] Build city / port / warship / SAM, verify construction sounds sit
naturally in the mix
- [x] Trigger alliance suggest/break, verify they match loudness of
build sounds
- [x] Trigger many simultaneous events, verify the mix is comfortable
- [x] Verify no audio truncation / glitching / clipping

Addresses #3728
2026-04-22 14:35:35 -07:00
Jarifa 0801798fbd Feat: Alliance and betrayal hotkeys (#3110)
Original Feature request by @FloPinguin  
Resolves #3077 

## Description:

Adds hotkeys for Requesting alliances and breaking alliances. This
allows for players to send or break alliances whose tile is under the
cursor, without opening the radial menu.

Keybinds:
New "Ally Keybinds" section in Settings -> Keybinds
Request alliance: Default: K - sends an alliance request to the
player/bot/nation under the cursor
Break alliance: Default: L - breaks the alliance with the player at the
cursor

Behavior:
- Cursor must be over a tile owned by the target player. The action runs
only when the game allows it, following the same logic as the radial
menu. (canSendAllianceRequest and canBreakAlliance)
- When an alliance request is sent, the events log shows: "Alliance
request sent to [target]" for confirmation. No extra message for
breaking an alliance (betrayal/debuff message already exists and is sent
upon breaking an alliance)

## Screenshots:
Keybind menu:
<img width="739" height="595" alt="image"
src="https://github.com/user-attachments/assets/ee958eab-fd50-4971-85c5-dfd49c6f0bdc"
/>
In game logs:
<img width="373" height="232" alt="image"
src="https://github.com/user-attachments/assets/2cf6bb07-5f0d-425a-82d3-65a44fef99c5"
/>

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


Discord username:
_Dave9595_
2026-04-21 14:34:51 -07:00
FloPinguin eedb90ffb5 Fix game ID display for team games 🪪 (#3734)
## Description:

Game ID display was looking weird in team games...

Before:

<img width="389" height="321" alt="image"
src="https://github.com/user-attachments/assets/cf39b490-cfba-4c3a-86af-8f9498380eae"
/>

After:

<img width="394" height="323" alt="image"
src="https://github.com/user-attachments/assets/9e828169-b267-4627-85eb-548dca224a8a"
/>

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

FloPinguin
2026-04-21 14:33:00 -07:00
Ivan Batsulin 29a1e8dfda feat: multi-warship selection with Shift+drag box (#3677)
Resolves #3666

## Description:

Adds RTS-style box selection for warships. Hold Shift and drag (desktop)
or long-press and drag (touch/mobile) to draw a selection rectangle —
all player-owned warships inside get selected at once. A subsequent
click/tap on water sends them all to that location.

- `SelectionBoxLayer` — pixel-dashed rectangle in world-space, player
territory color; shared between desktop and touch
- `UILayer` — same pulsing selection outline on each box-selected
warship; clears correctly when switching between single/multi selection
- `UnitLayer` — finds warships in screen rect, filters inactive ships
before sending; touch support included
- `InputHandler` — Shift+drag and touch long-press+drag both emit
selection box events; cursor becomes crosshair on Shift; discards active
ghost structure on Shift press; configurable via `shiftKey` keybind
- `Transport` — single atomic `move_multiple_warships` intent (no split
on socket drop)
- `Schemas` + `ExecutionManager` + `MoveMultipleWarshipsExecution` —
server fans out atomic intent into individual `MoveWarshipExecution` per
ship
- `DynamicUILayer` — `MoveIndicatorUI` chevron animation on target tile
for both single and multi move
- `UnitDisplay` — warship tooltip Shift hint via `translateText`
- `HelpModal` — new hotkey row: Shift + drag → select multiple warships

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

## UI update
### Mouse + Keyboard


https://github.com/user-attachments/assets/3f35ab5e-1f3c-4c5d-bc4f-aabccf64dc60

### Touch


https://github.com/user-attachments/assets/0d6aec3f-44fa-4fee-b5c6-b267b9b14d79

##
## Please put your Discord username so you can be contacted if a bug or
regression is found:

fghjk_60845
2026-04-21 14:06:07 -07:00
evanpelle 78d4b301a6 worker: stop trusting client-supplied headers for WS client IP
The WS message handler read X-Forwarded-For[0] (the leftmost entry,
which is client-controllable) to key a per-IP rate limiter and to
populate the IP passed to Turnstile, Client, and the unique-IP winner
check. A client could send a different XFF per connection to bypass
all of these and indefinitely grow the limiter map.

- Drop the per-IP limiter entirely; Cloudflare already rate-limits at
  the edge and no other path used this limiter.
- Add getClientIp(): prefer cf-connecting-ip (set by Cloudflare), fall
  back to req.socket.remoteAddress (always nginx since workers bind
  127.0.0.1). Any XFF/X-Real-IP fallback would just give CF's edge IP
  or a spoofable value, so they're omitted.
2026-04-20 11:46:05 -07:00
Alex Pickett 328b8859d3 Merge commit from fork 2026-04-20 11:18:02 -07:00
Ryan c3d7d0373e Improve ingame moderation for admins (#3678)
## Description:

Players with the `admin` flare can now kick players from any game
(including public lobbies), not just the lobby creator in private
lobbies.

## 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-04-20 11:09:04 -07:00
RickD004 52033597ef Update Britannia and take its Classic version off rotation (#3710)
## Description:

Similar to how Europe classic was taken off rotation, we do the same
with Britannia. The newer Britannia was slightly updated to include the
rivers of the classic version, this is because of feedback from players
in the discord server who say the rivers in the classic version are an
important part of gameplay. Map otherwise keeps same nations and size.

## 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-04-18 21:36:49 -07:00
Ivan Batsulin 20f428d19e Fix middle-click SAM not upgrading other buildings when SAM is unaffo… (#3670)
Resolves #3511

## Description:
When middle-clicking a SAM launcher you own, the game calls
findAndUpgradeNearestBuilding which queries all upgradeable structures
near the clicked tile. If you can't afford the SAM upgrade, canUpgrade
is false for the SAM (because canBuildUnitType returns false when gold <
cost), so the SAM is excluded from the candidates list. If a nearby
building (e.g. a Factory) can be upgraded, it gets picked as the
"nearest" target and is upgraded instead — spending gold the player was
saving for the SAM.

The fix: after finding the best upgrade candidate, check if there's an
owned SAM within the same search radius as the clicked tile. If there
is, but the best candidate is not a SAM (meaning the SAM couldn't be
afforded), do nothing instead of upgrading the other building. This
ensures middle-clicking a SAM either upgrades it or takes no action.

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

fghjk_60845
2026-04-18 21:35:23 -07:00
FloPinguin 12b06fa0b2 Pathfinding Fixes (Water Nukes / Lakes) 💧 (#3714)
## Description:

Fixes water-pathfinding errors that started appearing after the first
water nuke and persisted across the rest of the match.
Users reported warships "getting stuck" (stopped moving).

<img width="374" height="281" alt="image"
src="https://github.com/user-attachments/assets/de38b8f1-c4d8-469e-b3a7-d0cef4dfb772"
/>

### Summary

- The new `AbstractGraphBuilder.buildClusterConnectionsFromCache` was
buggy _(The cached edge costs reused by "clean" clusters were keyed by
tile pair without their original `(clusterX, clusterY)`, so a boundary
edge could be re-stamped with the wrong cluster and become untraversable
by the query-time single-cluster bounded A*. The cache now stores `{
cost, clusterX, clusterY }` and `buildClusterConnectionsFromCache`
preserves the original attribution when re-adding the edge.)_
- Warships: `findTargetUnit` now skips trade ships that are not in the
warship's water component, avoiding pathfinding to provably unreachable
targets.
- Warships: On `patrol` `NOT_FOUND`, clear `targetTile` so the warship
picks a new target. This is a defensive guard for the rare case where a
water nuke splits the component between target selection and pathfinding
- without it, the warship retries the same now-unreachable target every
tick and spams the log forever.

### Test

- Added a Warship test verifying that trade ships in a different water
component are not targeted.

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

FloPinguin
2026-04-18 21:32:21 -07:00
FloPinguin 4e04bed44c Show game ID ingame 🪪 (#3674)
## Description:

Instead of begging youtubers to share their game id to be able to debug:

Display the current game ID in the top-right corner of the in-game
leaderboard panel (there was unused space)

<img width="391" height="326" alt="image"
src="https://github.com/user-attachments/assets/8b0aa7c2-fc8c-48e5-ae11-edd60fd40de9"
/>

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

FloPinguin
2026-04-17 17:48:37 -07:00
RickD004 ec8884410c Add new Bering Sea map, reduce Strait rotation (#3706)
## Description:

Re-submission of older PR:
https://github.com/openfrontio/OpenFrontIO/pull/3617
<img width="612" height="396" alt="image"
src="https://github.com/user-attachments/assets/955a0b2e-1df9-4fa3-a389-235f46a90f69"
/>

Regarding Bering Sea and Bering strait maps:
<img width="576" height="87" alt="image"
src="https://github.com/user-attachments/assets/f57031eb-f9c0-4e1e-83ff-204df51bb6c2"
/>
<img width="589" height="93" alt="image"
src="https://github.com/user-attachments/assets/629e71ba-489f-41cf-b67e-2476af8704f2"
/>

Because of mixed opinions about replacing the maps, i propose at least
this temporary compromise: Bering Sea gets added as a new map and Bering
Strait gets its rotation lowered to a small number. Since the classic
maps are probably being taken off rotation, we should have some small
breathing space for the 2 maps.

In the near future we should discuss between mapmakers in the dev server
whether we keep, replace or completely take Bering Strait off rotation,
and/or a community poll.

## 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-04-17 17:36:38 -07:00
FloPinguin bcd9cd6af5 Cache shared-water computation for nation port placement 💧 (#3696)
## Description:

- Cache `sharedWaterComponents` globally with a 30-tick (~3s) TTL so all
nations share one `O(total_border_tiles)` pass instead of each nation
re-scanning every other player's border on every call.
- Treat ocean as always-shared: any ocean neighbor short-circuits as a
valid port site, skipping the `getWaterComponent` lookup in both the
build pass and the per-tile port check.
- Exclude bots and mutually-embargoed players from the trade-partner
candidate set, so nations no longer avoid port sites that only "share"
water with a player they can never trade with.

Port placement is not time-critical, so the 3-second staleness is
acceptable and lets the expensive build amortize across many attack
cycles.

### Performance
Benchmarked on World map (2000×1000, 61 nations) with the realistic call
pattern of ~3 nations invoking `sharedWaterComponents` per tick:

- **Before (main):** ~414 μs per tick
- **After:** ~8 μs per tick amortized (29/30 ticks hit the warm cache;
1/30 rebuilds)
- **~50× faster** on this AI hot path

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

FloPinguin
2026-04-17 17:34:45 -07:00
FloPinguin 0801cad0b5 Fix NaN coordinates in Warship patrol logic 🚢 (#3697)
## Description:

This PR fixes the `Invalid coordinates: NaN,NaN` crash during Warship
patrol execution.

### Root cause

`WarshipExecution.randomTile` picks a patrol destination inside
`warshipPatrolRange / 2` of the current patrol tile. When a search fails
to find a valid tile, the range expands by 50% per retry (`100 → 150 →
225 → 337`) and becomes odd. Once odd, `warshipPatrolRange / 2` is a
float (e.g. `112.5`), which is handed straight to
`PseudoRandom.nextInt`:

```ts
Math.floor(this.rng() * (max - min)) + min;
```

With a float `min`, this returns `integer + float` - a float. Despite
its name, `nextInt` was silently returning a non-integer. From there:

- `x = mg.x(patrolTile) + floatOffset` → float
- `mg.isValidCoord(floatX, floatY)` → `true` (only bounds were checked)
- `mg.ref(floatX, floatY)` → `yToRef[floatY] + floatX` → `undefined +
float` → `NaN`
- `hasWaterComponent(NaN, …)` → `miniMap.ref(NaN, NaN)` → **throw**

### Why this only started crashing recently

The float‑leaking `nextInt` bug has been latent since at least the
pathfinding refactor (#2866, January), which introduced the
`hasWaterComponent` check. It was invisible because the guard directly
above it short‑circuited on `NaN`:

```ts
if (!this.mg.isOcean(tile) || (!allowShoreline && this.mg.isShoreline(tile))) continue;
```

For a `NaN` tile ref, `terrain[NaN]` is `undefined`, so:

- `isOcean(NaN)` → `Boolean(undefined & OCEAN_BIT)` → **`false`**
- `isLand(NaN)` → **`false`**
- `isWater(NaN)` → `!isLand(NaN)` → **`true`**

Before: `!isOcean(NaN)` was `true`, execution hit `continue`, and the
poisoned ref never reached `hasWaterComponent`. The "Trading in lakes"
PR (#3653) relaxed that single line to allow patrol on lakes:

```diff
- if (!this.mg.isOcean(tile) || ...) continue;
+ if (!this.mg.isWater(tile) || ...) continue;
```

Because `isWater(NaN)` is `true`, `!isWater(NaN)` is now `false` -
execution falls through to `hasWaterComponent(NaN, …)` and crashes.
#3653 didn't introduce the bug; it just happened to remove the
accidental NaN filter that was hiding it.

### Changes

- **`PseudoRandom.nextInt`** - root‑cause fix. Floors both `min` and
`max` so `nextInt` always returns an integer regardless of what callers
pass. Future callers can't re‑trip this trap.
- **`WarshipExecution.randomTile`** - replaced the unsafe
`this.warship.patrolTile()!` non‑null assertion with a proper
`undefined` guard that returns early.
- **`GameMap.isValidCoord`** - defense in depth: also requires
`Number.isInteger(x)` and `Number.isInteger(y)`. Non‑integer coords can
still be produced outside `nextInt` (trig, arithmetic); this makes
`ref()` fail loudly at the boundary instead of silently producing `NaN`
refs.

### Original stacktrace

Please paste the following in your bug report in Discord:
Game crashed!
game id: gGicMpDh
client id: wXE5SpT2
Error: Invalid coordinates: NaN,NaN
Message: Error: Invalid coordinates: NaN,NaN
at at.ref
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:64853)
at r_.hasWaterComponent
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:243326)
at l_.hasWaterComponent
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:260740)
at b1.randomTile
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:92634)
at b1.patrol
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:91728)
at b1.tick
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:89996)
at
https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:251463
    at Array.forEach (<anonymous>)
at l_.executeNextTick
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:251383)
at p_.executeNextTick
(https://nightly.openfront.dev/assets/Worker.worker-DL_guV2P.js:31:271256)

Discord:
https://discord.com/channels/1284581928254701718/1494336024740888667

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

FloPinguin
2026-04-17 17:34:12 -07:00
dependabot[bot] bf79a0cd56 Bump protobufjs from 7.5.3 to 7.5.5 in the npm_and_yarn group across 1 directory (#3698)
Bumps the npm_and_yarn group with 1 update in the / directory:
[protobufjs](https://github.com/protobufjs/protobuf.js).

Updates `protobufjs` from 7.5.3 to 7.5.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/protobufjs/protobuf.js/releases">protobufjs's
releases</a>.</em></p>
<blockquote>
<h2>protobufjs: v7.5.4</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.3...protobufjs-v7.5.4">7.5.4</a>
(2025-08-15)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760">5a3769a</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md">protobufjs's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v8.0.0...protobufjs-v8.0.1">8.0.1</a>
(2026-03-11)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>bump protobufjs dependency version for cli package (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2128">#2128</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/549b05ecd95e23da40fa1a36a9336c57946b8377">549b05e</a>)</li>
<li>correct json syntax in tsconfig.json (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2120">#2120</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/80656255c75000f3e954e036cdfcb5bfd0a8c687">8065625</a>)</li>
<li><strong>descriptor:</strong> guard oneof index for non-Type parents
(<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2122">#2122</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/1cac5cf811d0855b27dcde73a3a04d15efde3728">1cac5cf</a>)</li>
<li>do not allow setting <strong>proto</strong> in Message constructor
(<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2126">#2126</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/f05e3c3bdd0b3c2cddbf8540bb5bd4d394a693ad">f05e3c3</a>)</li>
<li>filter invalid characters from the type name (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2127">#2127</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/535df444ac060243722ac5d672db205e5c531d75">535df44</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.4...protobufjs-v8.0.0">8.0.0</a>
(2025-12-16)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>add Edition 2024 Support (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2060">#2060</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add Edition 2024 Support (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2060">#2060</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/53e8492cbaae2c741801fa50b5f908ff5129c3d7">53e8492</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.3...protobufjs-v7.5.4">7.5.4</a>
(2025-08-15)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760">5a3769a</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/b7bdfaf91d7bf279326f2d043b633da0a2dbfe47"><code>b7bdfaf</code></a>
chore: release 7.5.5</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/ff7b2afef8754837cc6dc64c864cd111ab477956"><code>ff7b2af</code></a>
fix: filter invalid characters from the type name (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2127">#2127</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/086b19d00d1d01e801d6ccc2ae3f207bb1b06482"><code>086b19d</code></a>
fix: do not allow setting <strong>proto</strong> in Message constructor
(<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2126">#2126</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/827ff8e48253e9041f19ac81168aa046dbdfb041"><code>827ff8e</code></a>
chore: release master (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2093">#2093</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760"><code>5a3769a</code></a>
fix: invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)</li>
<li>See full diff in <a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.3...protobufjs-v7.5.5">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~fenster">fenster</a>, a new releaser for
protobufjs since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=protobufjs&package-manager=npm_and_yarn&previous-version=7.5.3&new-version=7.5.5)](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-04-17 17:33:03 -07:00
FloPinguin ae96eb7e98 Fix nation nuke crash when attacker has no remaining tiles 🛡️ (#3703)
## Description:

Fixes a game crash (`Error: array must not be empty`) thrown from
`PseudoRandom.randElement` when a nation tries to pick a nuke target
whose territory no longer exists.

## Root cause

`NationNukeBehavior.findBestNukeTarget` calls
`findIncomingAttackPlayer`, which iterates the player's
`_incomingAttacks`. `AttackImpl` instances can linger in this array past
the point where the attacker has lost all tiles — the attack is only
removed on explicit `delete()` and `removeOnDeath` cleanup isn't
guaranteed to run before other executions tick within the same turn. A
dead attacker gets returned as the nuke target, `randTerritoryTileArray`
samples their (empty) territory, and `randElement` throws on the empty
array.

## Fix

- `Player.incomingAttacks()` now filters out attacks whose attacker is
no longer alive, so consumers can't observe stale references from
mid-tick deaths.
- `randTerritoryTile` guards against `numTilesOwned() === 0` before
falling back to `randElement(p.tiles())` as a defense-in-depth safeguard
at the util level.
- `PlayerImpl.toUpdate()` now uses the `incomingAttacks()` /
`outgoingAttacks()` accessors (rather than the raw `_` arrays) so
serialized client state stays consistent with the server-side view.

`outgoingAttacks()` is intentionally left unfiltered, the engine relies
on seeing in-flight attacks during their retreat phase after a target is
conquered (attack merging/cancellation in `AttackExecution.init`).

### Bug report from discord

Please paste the following in your bug report in Discord:
Game crashed!
game id: LQDSWbh6
client id: JjwysSLN
Error: array must not be empty
Message: Error: array must not be empty
at sa.randElement
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:28:39166)
at H1
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:116429)
at Jc
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:116135)
at G1.maybeSendNuke
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:117597)
at n5.tick
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:171764)
at https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:251463
    at Array.forEach (<anonymous>)
at c.executeNextTick
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:251383)
at b.executeNextTick
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:271256)
at S_
(https://main.openfront.dev/assets/Worker.worker-DoPM94lr.js:31:366356)

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

FloPinguin
2026-04-17 17:32:49 -07:00
Aotumuri cfb731595d mls (v5.1) (#3705)
## Description:

Version identifier within MLS: v5.1

[Changed languages]
- bg
- de-CH
- fr
- id
- ru
- uk
- zh-CN

[Change volume]
- Changed languages: 8
- Changed files: 8
- Changed lines: 9222
- metadata.json: unchanged

Final reviewer: meow02952

This PR was generated by the PR sender tool, then checked and submitted
by the final reviewer.

## 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:
aotumuri
2026-04-17 17:31:43 -07:00
Ivan Batsulin e5e1211480 feat: add Shift+ modifier support for keybinds (#3679)
## Description:

This PR adds support for `Shift+<key>` keybind combinations across the
entire keybind system.

Previously, keybinds only supported a single key (e.g. `KeyB` for boat
attack). Now any keybind can be configured as `Shift+KeyB`, which will
only trigger when Shift is held down simultaneously.

Enables to use Shift + A for "select all" feature from #3677 

**Changes:**
- `InputHandler.ts`: Added `parseKeybind()` helper that parses
`"Shift+KeyB"` → `{ shift: true, code: "KeyB" }`. Added
`keybindMatchesEvent()` for consistent matching across all keyup/keydown
handlers. Updated `resolveBuildKeybind()` and all keybind comparisons to
respect the shift modifier.
- `SettingKeybind.ts`: When recording a keybind, lone modifier keys
(Shift, Ctrl, etc.) are skipped — the component waits for the actual
key. If Shift is held when the key is pressed, the value is stored as
`"Shift+<code>"`.
- `Utils.ts`: `formatKeyForDisplay()` now handles the `Shift+` prefix,
displaying e.g. `"Shift+B"`.
- `tests/InputHandler.test.ts`: Added 6 tests covering Shift+ keybind
matching, negative cases (plain key not triggering Shift-bound action),
coexistence of `Digit1` and `Shift+Digit1` on different actions, and
Numpad alias support with Shift.

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

## UI changes:

<img width="2255" height="2070" alt="CleanShot 2026-04-15 at 20 23
25@2x"
src="https://github.com/user-attachments/assets/96c19fc3-6294-40b7-82eb-3fde52b71618"
/>


## Please put your Discord username so you can be contacted if a bug or
regression is found:

fghjk_60845
2026-04-16 19:46:01 -07:00