Skip to content

Conversation

wnusair
Copy link

@wnusair wnusair commented Sep 1, 2025

Description:

SAM Launcher defense radius visible
image

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

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

mayfly404

Kipstz and others added 30 commits August 5, 2025 02:48
…io#1597)

## Description:

This PR implements a new feature allowing automatic upgrade of the
nearest building using the middle mouse button. This feature greatly
simplifies the upgrade process that previously required a right-click +
building recreation.

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

Kipstzz

---------

Co-authored-by: Scott Anderson <[email protected]>
…tio#1643)

## Description:

Checks that each lang file’s lang_code matches its filename and that the
flag SVG exists.
Reports all errors in a single test run for easier debugging.

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

aotumuri

Co-authored-by: Drills Kibo <[email protected]>
## Description:

Added a red delete button with trash can icon to the right-click radial
menu that allows players to voluntarily delete their own units.

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

Kipstz

<img width="286" height="209" alt="image"
src="https://github.com/user-attachments/assets/85142be3-2aa5-4c84-ab30-0c68289c8f85"
/>

---------

Co-authored-by: Drills Kibo <[email protected]>
## Description:

Strict mode is causing docker deployments to fail. This commit reverts
only the strict mode setting itself, while keeping the code changes, so
that we can re-enable it more easily in the future.

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
Fixes openfrontio#1559

## Description:

The current Mars map has several issues:
- The map is very underdetailed
  - The coastlines are very smooth and visually unappealing
  
- The map was created from an incompatible source image, which results
in the height data being very wrong
  - As a result the map hardly resembles Mars at all.
  - There is too much land
  - The major landmass is almost entirely covered in plains
  - The ocean doesn't match the heightmap

- The gameplay is boring
  - The map is very succeptable to snowballing issues
  - The map seems commonly disliked in the community

I attempted to remedy this. 
- The water level and elevation are calculated from accurate height data
- Water level is much higher making the map much more interesting, both
in the gameplay and visual aspect.
  - The map has several contitents which should slow down snowballing
- The map is much more detailed overall
- I added a lot more NPC's. 8 for such a big map just wasn't enough.
<img width="2500" height="1150" alt="Mars_Out2"
src="https://github.com/user-attachments/assets/7b7009f7-6376-4059-b731-86931df8f926"
/>


- [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
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

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

aceralex

---------

Co-authored-by: Drills Kibo <[email protected]>
…ntio#1680)

## Description:

Switches away from ts-jest in favor of @swc/jest. On my local I observe
a ten-fold decrease in how long it takes the test suite to run. No
changes are required to how our existing tests are written.

Benchmarking
old: 24.658s
new: 2.268s


ts-jest (old)
```
Test Suites: 29 passed, 29 total
Tests:       215 passed, 215 total
Snapshots:   0 total
Time:        24.658 s
Ran all test suites.
```

swc-jest (new)
```
Test Suites: 29 passed, 29 total
Tests:       215 passed, 215 total
Snapshots:   0 total
Time:        2.268 s
Ran all test suites.
```

Fixes openfrontio#1679


## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

slyty
## Description:

This pull request adds support for ICU (Intl MessageFormat) syntax in
the translation system.
Existing translation files may need to be updated to fully leverage ICU
features.

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

DISCORD_USERNAME
…ontio#1723)

## Description:

Add frontend-approver and backend-approver to CODEOWNERS file

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
…ontio#1481)

Bumps the npm_and_yarn group with 2 updates in the / directory:
[on-headers](https://github.com/jshttp/on-headers) and
[compression](https://github.com/expressjs/compression).

Updates `on-headers` from 1.0.2 to 1.1.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jshttp/on-headers/releases">on-headers's
releases</a>.</em></p>
<blockquote>
<h2>1.1.0</h2>
<h2>Important</h2>
<ul>
<li>Fix <a
href="https://www.cve.org/CVERecord?id=CVE-2025-7339">CVE-2025-7339</a>
(<a
href="https://github.com/jshttp/on-headers/security/advisories/GHSA-76c9-3jph-rj3q">GHSA-76c9-3jph-rj3q</a>)</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Migrate CI pipeline to GitHub actions by <a
href="https://github.com/carpasse"><code>@​carpasse</code></a> in <a
href="https://redirect.github.com/jshttp/on-headers/pull/12">jshttp/on-headers#12</a></li>
<li>fix README.md badges by <a
href="https://github.com/carpasse"><code>@​carpasse</code></a> in <a
href="https://redirect.github.com/jshttp/on-headers/pull/13">jshttp/on-headers#13</a></li>
<li>add OSSF scorecard action by <a
href="https://github.com/carpasse"><code>@​carpasse</code></a> in <a
href="https://redirect.github.com/jshttp/on-headers/pull/14">jshttp/on-headers#14</a></li>
<li>fix: use <code>ubuntu-latest</code> as ci runner by <a
href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a>
in <a
href="https://redirect.github.com/jshttp/on-headers/pull/19">jshttp/on-headers#19</a></li>
<li>ci: apply OSSF Scorecard security best practices by <a
href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a>
in <a
href="https://redirect.github.com/jshttp/on-headers/pull/20">jshttp/on-headers#20</a></li>
<li>👷 add upstream change detection by <a
href="https://github.com/ctcpip"><code>@​ctcpip</code></a> in <a
href="https://redirect.github.com/jshttp/on-headers/pull/31">jshttp/on-headers#31</a></li>
<li>✨ add script to update known hashes by <a
href="https://github.com/ctcpip"><code>@​ctcpip</code></a> in <a
href="https://redirect.github.com/jshttp/on-headers/pull/32">jshttp/on-headers#32</a></li>
<li>💚 update CI - add newer node versions by <a
href="https://github.com/ctcpip"><code>@​ctcpip</code></a> in <a
href="https://redirect.github.com/jshttp/on-headers/pull/33">jshttp/on-headers#33</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/carpasse"><code>@​carpasse</code></a>
made their first contribution in <a
href="https://redirect.github.com/jshttp/on-headers/pull/12">jshttp/on-headers#12</a></li>
<li><a
href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a>
made their first contribution in <a
href="https://redirect.github.com/jshttp/on-headers/pull/19">jshttp/on-headers#19</a></li>
<li><a href="https://github.com/ctcpip"><code>@​ctcpip</code></a> made
their first contribution in <a
href="https://redirect.github.com/jshttp/on-headers/pull/31">jshttp/on-headers#31</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0">https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jshttp/on-headers/blob/master/HISTORY.md">on-headers's
changelog</a>.</em></p>
<blockquote>
<h1>1.1.0 / 2025-07-17</h1>
<ul>
<li>Fix <a
href="https://www.cve.org/CVERecord?id=CVE-2025-7339">CVE-2025-7339</a>
(<a
href="https://github.com/jshttp/on-headers/security/advisories/GHSA-76c9-3jph-rj3q">GHSA-76c9-3jph-rj3q</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jshttp/on-headers/commit/4b017af88f5375bbdf3ad2ee732d2c122e4f52b0"><code>4b017af</code></a>
1.1.0</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/b636f2d08e6c1e0a784b53a13cd61e05c09bb118"><code>b636f2d</code></a>
♻️ refactor header array code</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/3e2c2d46c3e9592f6a1c3a3a1dbe622401f95d39"><code>3e2c2d4</code></a>
✨ ignore falsy header keys, matching node behavior</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/172eb41b99a5a290b27a2c43fe602ca33aa1c8ce"><code>172eb41</code></a>
✨ support duplicate headers</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/c6e384908c9c6127d18831d16ab0bd96e1231867"><code>c6e3849</code></a>
🔒️ fix array handling</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/6893518341bb4e5363285df086b3158302d3b216"><code>6893518</code></a>
💚 update CI - add newer node versions</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/56a345d82b51a0dcb8d09f061f87b1fd1dc4c01e"><code>56a345d</code></a>
✨ add script to update known hashes</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/175ab217155d525371a5416ff059f895a3a532a6"><code>175ab21</code></a>
👷 add upstream change detection (<a
href="https://redirect.github.com/jshttp/on-headers/issues/31">#31</a>)</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/ce0b2c8fcd313d38d3534fb731050dc16e105bf6"><code>ce0b2c8</code></a>
ci: apply OSSF Scorecard security best practices (<a
href="https://redirect.github.com/jshttp/on-headers/issues/20">#20</a>)</li>
<li><a
href="https://github.com/jshttp/on-headers/commit/1a38c543e75cd06217b449531de10b1758e35299"><code>1a38c54</code></a>
fix: use <code>ubuntu-latest</code> as ci runner (<a
href="https://redirect.github.com/jshttp/on-headers/issues/19">#19</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.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/~ulisesgascon">ulisesgascon</a>, a new
releaser for on-headers since your current version.</p>
</details>
<br />

Updates `compression` from 1.8.0 to 1.8.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/expressjs/compression/releases">compression's
releases</a>.</em></p>
<blockquote>
<h2>v1.8.1</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(docs): update multiple links from http to https by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/compression/pull/222">expressjs/compression#222</a></li>
<li>ci: add dependabot for github actions by <a
href="https://github.com/bjohansebas"><code>@​bjohansebas</code></a> in
<a
href="https://redirect.github.com/expressjs/compression/pull/207">expressjs/compression#207</a></li>
<li>build(deps): bump github/codeql-action from 2.23.2 to 3.28.15 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/228">expressjs/compression#228</a></li>
<li>build(deps): bump ossf/scorecard-action from 2.3.1 to 2.4.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/229">expressjs/compression#229</a></li>
<li>build(deps-dev): bump eslint-plugin-import from 2.26.0 to 2.31.0 by
<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/230">expressjs/compression#230</a></li>
<li>build(deps-dev): bump supertest from 6.2.3 to 6.3.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/231">expressjs/compression#231</a></li>
<li>[StepSecurity] ci: Harden GitHub Actions by <a
href="https://github.com/step-security-bot"><code>@​step-security-bot</code></a>
in <a
href="https://redirect.github.com/expressjs/compression/pull/235">expressjs/compression#235</a></li>
<li>build(deps): bump github/codeql-action from 3.28.15 to 3.29.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/243">expressjs/compression#243</a></li>
<li>build(deps): bump actions/upload-artifact from 4.3.1 to 4.6.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/239">expressjs/compression#239</a></li>
<li>build(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/240">expressjs/compression#240</a></li>
<li>build(deps): bump actions/checkout from 4.1.1 to 4.2.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/241">expressjs/compression#241</a></li>
<li>build(deps-dev): bump eslint-plugin-import from 2.31.0 to 2.32.0 by
<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/compression/pull/244">expressjs/compression#244</a></li>
<li>deps: [email protected] by <a
href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a>
in <a
href="https://redirect.github.com/expressjs/compression/pull/246">expressjs/compression#246</a></li>
<li>Release: 1.8.1 by <a
href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a>
in <a
href="https://redirect.github.com/expressjs/compression/pull/247">expressjs/compression#247</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
made their first contribution in <a
href="https://redirect.github.com/expressjs/compression/pull/228">expressjs/compression#228</a></li>
<li><a
href="https://github.com/step-security-bot"><code>@​step-security-bot</code></a>
made their first contribution in <a
href="https://redirect.github.com/expressjs/compression/pull/235">expressjs/compression#235</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/expressjs/compression/compare/1.8.0...v1.8.1">https://github.com/expressjs/compression/compare/1.8.0...v1.8.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/expressjs/compression/blob/master/HISTORY.md">compression's
changelog</a>.</em></p>
<blockquote>
<h1>1.8.1 / 2025-07-17</h1>
<ul>
<li>deps: on-headers@~1.1.0
<ul>
<li>Fix <a
href="https://www.cve.org/CVERecord?id=CVE-2025-7339">CVE-2025-7339</a>
(<a
href="https://github.com/expressjs/on-headers/security/advisories/GHSA-76c9-3jph-rj3q">GHSA-76c9-3jph-rj3q</a>)</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/expressjs/compression/commit/83a0c45fe190f4fcb8b515c18065db9cb9029dd1"><code>83a0c45</code></a>
1.8.1</li>
<li><a
href="https://github.com/expressjs/compression/commit/ce62713129f4b33eac4b833e1722410091646395"><code>ce62713</code></a>
deps: [email protected] (<a
href="https://redirect.github.com/expressjs/compression/issues/246">#246</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/f4acb23985fa345318d34d4a96acf555a883efeb"><code>f4acb23</code></a>
build(deps-dev): bump eslint-plugin-import from 2.31.0 to 2.32.0 (<a
href="https://redirect.github.com/expressjs/compression/issues/244">#244</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/6eaebe63f2ecac191d402c570bde140488435c4c"><code>6eaebe6</code></a>
build(deps): bump actions/checkout from 4.1.1 to 4.2.2 (<a
href="https://redirect.github.com/expressjs/compression/issues/241">#241</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/37e062312fd270f84b5f50f7c6f88312609633f5"><code>37e0623</code></a>
build(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.2 (<a
href="https://redirect.github.com/expressjs/compression/issues/240">#240</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/bc436b26283c2f85a9711085dd0e4a580de50ba7"><code>bc436b2</code></a>
build(deps): bump actions/upload-artifact from 4.3.1 to 4.6.2 (<a
href="https://redirect.github.com/expressjs/compression/issues/239">#239</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/2f9f5726751ecf12f7c46a9d1493bcd1966e09a7"><code>2f9f572</code></a>
build(deps): bump github/codeql-action from 3.28.15 to 3.29.2 (<a
href="https://redirect.github.com/expressjs/compression/issues/243">#243</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/5f13b148d2a1a2daaa8647e03592214bb240bf18"><code>5f13b14</code></a>
[StepSecurity] ci: Harden GitHub Actions (<a
href="https://redirect.github.com/expressjs/compression/issues/235">#235</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/76e094548125afbf8089a482d5982dc96c7ce398"><code>76e0945</code></a>
build(deps-dev): bump supertest from 6.2.3 to 6.3.4 (<a
href="https://redirect.github.com/expressjs/compression/issues/231">#231</a>)</li>
<li><a
href="https://github.com/expressjs/compression/commit/ae6ee809dc0cb40febaf2a5bff298465bd5a207f"><code>ae6ee80</code></a>
build(deps-dev): bump eslint-plugin-import from 2.26.0 to 2.31.0 (<a
href="https://redirect.github.com/expressjs/compression/issues/230">#230</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/expressjs/compression/compare/1.8.0...v1.8.1">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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Description:

Added 2-fingers control for map with trackpad

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

pierre_brtr
## Description:

Enable the `sort-keys` eslint rule.

Fixes openfrontio#1629

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
## Description:

Problem: attacking a player right before accepting an alliance request
is very effective since the requester can't fight back or reclaim his
territory without canceling the alliance and being penalized with the
traitor debuff.

Change:
- Attacking a player after he requested an alliance automatically
rejects the request
- No changes to existing attacks in both directions, only new attacks
affect the request

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

IngloriousTom
## Description:

The websocket message handler functions have gotten quite large. This
change extracts them to functions in their own file, and extracts the
`"join"` message acceptance logic into its own function allowing for all
cases to be accounted for when we add error messages in openfrontio#1447.

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
## Description:

Enable `@total-typescript/ts-reset`

Fixes openfrontio#1760

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
## Description:

Update the code for strict mode.

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
## Description:

Enable eslint warning for
`@typescript-eslint/consistent-type-assertions`. While build warnings
are generally a discouraged pattern, we are actively working to drive
the number of warnings down to zero, at which point we will convert the
warnings to errors.

## 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
- [ ] I have read and accepted the CLA agreement (only required once).
## Description:

Since the in-game Settings became their own modal in v24, it blocks game
control but the game goes on in the background. On mobile it is full
screen so you don't even notice the game still playing in the
background.

Of course players understand that a Multiplayer game will move on. But
for Single Player, the game mode played by beginners too, you'd expect
the game to be paused and are surprised when it isn't. Same goes for
Replays.

This PR fixes it:

- Pause when opening the in-game Settings modal during replay or single
player game.
- Unpause again when closing the Settings modal (if not already paused
before opening the Settings).
- The icon for pause/unpause isn't switched in GameRightSideBar during
this, as the sidebar is blurred in the background anyway.

## 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
- [ ] I have read and accepted the CLA agreement (only required once).

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

tryout33

---------

Co-authored-by: Drills Kibo <[email protected]>
## Description:

Re-enable strict mode

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

Remove CLA from the PR description template and PR check. This is
handled through a dedicated status check, so the description is 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
## Description:

Describe the PR.
This PR makes the playerInfoOverlay collapsible by clicking on the
player name.

This overlay was covering a decent chunk of the mobile screen.


![1754819765364](https://github.com/user-attachments/assets/a74b0853-bdaa-4c1b-b28d-a270665f2955)

Now the details can be toggled by just clicking on the name freeing a
lot of the screen on mobile.

![1754819765361](https://github.com/user-attachments/assets/800917b9-1a98-4aa5-b4bd-e9c35e47e9d3)

## 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
- [x] I have read and accepted the CLA agreement (only required once).

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

DISCORD_USERNAME
tls_15

Co-authored-by: Drills Kibo <[email protected]>
## Description:
Resolve openfrontio#1652 

1. Add the ability to toggle **gold donations** and **troop donations**
for private lobbies
~2. Add relevant translations.~
3. Refactor `canDonate` to be specific to gold and troop donations 
4. Add placeholders for singleplayer mode if this is to be extended to
support that too.
5. Add Tests for Donate logic

### Screenshots:
<img width="1643" height="1788" alt="image"
src="https://github.com/user-attachments/assets/82b93400-a1f0-45f0-8b2b-a7f78dc0c3e9"
/>

_Private Lobby_

### Smoke Tests


![donatetroopsprivatelobby](https://github.com/user-attachments/assets/c6690bbc-958e-48a1-9cf1-e2b361dfb1b2)
_Testing Troop Send In Private Lobby_


![donatetroopsprivatelobby2](https://github.com/user-attachments/assets/698c7603-6b4b-4da7-91ab-7bdc38bb49a5)

_Troop Send Complete In Private Lobby_


![testtradepublicteams](https://github.com/user-attachments/assets/1010332c-3f38-4644-9218-46aa7141f578)
Confirming that public teams still works


## 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
- [X] I have read and accepted the CLA agreement (only required once).

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

DISCORD_USERNAME: cool_clarky

---------

Co-authored-by: Scott Anderson <[email protected]>
Co-authored-by: Drills Kibo <[email protected]>
## Description:

Enable various eslint rules.

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

Enable eslint rule `@stylistic/ts/indent`. Fixes openfrontio#1778

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

Enable more stylistic rules.

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

Enable eslint rule `quote-props`

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

Enable enforcement of various eslint style rules.

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

Have at least 2 clients and majority vote to decide a winner

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

---------

Co-authored-by: Scott Anderson <[email protected]>
## Description:

Restore code that was accidentally deleted in the previous PR.

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

Prefer `type.array()` over `z.array(type)`.

## 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
TheGiraffe3 and others added 9 commits August 26, 2025 21:59
## Description:

Adds more chat messages in several categories, as requested on
[Discord](https://discord.com/channels/1284581928254701718/1379092916827324426/1409862901816102964)

<img width="1440" height="800" alt="Screen Shot 2025-08-26 at 5 42 28
PM"
src="https://github.com/user-attachments/assets/f7c58cce-586c-47fa-b41b-728d5a829127"
/>
<img width="1440" height="800" alt="Screen Shot 2025-08-26 at 5 42 53
PM"
src="https://github.com/user-attachments/assets/8621e162-154d-48ee-a747-c7545f4e561d"
/>
<img width="1440" height="800" alt="Screen Shot 2025-08-26 at 5 42 41
PM"
src="https://github.com/user-attachments/assets/6d35da7e-6690-47ee-9850-094893f5b6ce"
/>

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

loymdayddaud
## Description:

Close openfrontio#1844

Fix `src/client/graphics/layers/EventsDisplay.ts` translation logic that
prevented messages without parameters from being translated.

Now it shows the message correctly:

<img width="383" height="179" alt="image"
src="https://github.com/user-attachments/assets/22a4dac5-ae68-40e1-bd11-f0f13e93b5fd"
/>

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

yumika8269
The issue raised describes context.restore using too much CPU. This PR
changes the layer order to reduce the number of context.restore and
context.save calls.

The order plays a role because every time a layer has to swap between
using transform (triggered by a layer's shouldTransform function
returning true) and not, it has to call context.save/context.restore.
This change simply reorders the layers so all layers which need
transform are grouped together at the start, and those who don't are at
the end.

Regarding testing, initially my plan was to add unit tests as this is an
easy thing to overlook. But the current testing setup doesn't play
nicely with pixijs, litjs, and a few others. I didn't want to make large
changes to the testing setup here, so instead I left a comment to remind
anyone making changes to pay attention to the order.

Fixes openfrontio#1894

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

regression is found:

Bornasm
## Description:

Simplify nation enemy selection to make nations more likely to launch
nukes.

Partially fixes openfrontio#1855 by addressing a v24 regression in nation 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
## Description:

In openfrontio#1860, some unused code was left behind. Remove the unused code.

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

Fixes openfrontio#1827.

Summary:
- Restore the code of `onScroll()` method which was modified by openfrontio#1717.
- Rework he `wheel` event logic to better distinguish between trackpad
pans and mouse wheel zooms. It now uses a heuristic where any scroll
event with a horizontal component (`deltaX !== 0`) is treated as a pan,
while purely vertical scrolls are treated as a zoom. This is a
compromise that fixes mouse wheel behavior, with the trade-off that
vertical-only trackpad swipes now also zoom (which is difficult for
human fingers to trigger).
- Solve the screen jittering problem when touching the screen by 2
fingers (which because when the second finger touches, `lastPointerX`
and `lastPointerY` are not recalculated in time.).

**Screen recording before fixing:**

(macbook, broken scroll zoom)


https://github.com/user-attachments/assets/5ba0fc24-2aec-4ecb-ab0f-2b0a0574d57e

(iphone, 2-fingers drag works well, but screen jittering exists)


https://github.com/user-attachments/assets/374f4f0f-688c-4b75-a20a-177144556c8c

**and after fixing:**

(macbook, scroll works well)


https://github.com/user-attachments/assets/b7e3447f-9936-4971-90c4-8644d0a9619d

(iphone, 2-fingers drag works well, no screen jittering)


https://github.com/user-attachments/assets/9d952082-a672-42b6-a117-7a9fed6ea5f0



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

yumika8269
## Description:

Derived from [LeviathanLevi
PR](openfrontio#1847)
Connect stations over water by automatically building bridges

Changes:
- Railroad construction to water is allowed from shore lines
- Railroad construction from water is allowed to shore lines too

This creates bridges a few tiles long.

<img width="1058" height="680" alt="image"
src="https://github.com/user-attachments/assets/493737b9-7aff-4ee2-88ea-7638f6af7c91"
/>

<img width="361" height="317" alt="image"
src="https://github.com/user-attachments/assets/24a71a7a-1ba1-4c88-a89e-876127024148"
/>

fixes openfrontio#1837

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

IngloriousTom
## Description:

Move the key to name mapping for difficulties into the translation
system.

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

Simplify `GameServer` message creation.

## 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
Copy link
Contributor

coderabbitai bot commented Sep 1, 2025

Walkthrough

Adds a Prettier import-sorting plugin and new dependencies, introduces an exported SAMRadiusLayer class for drawing SAM launcher radii, and updates GameRenderer imports and constructor fields (many made readonly). GameRenderer instantiates SAMRadiusLayer but the layer is not added to the rendered layers array in this diff.

Changes

Cohort / File(s) Summary
Tooling: Prettier & deps
\.prettierrc, package.json
Enables @trivago/prettier-plugin-sort-imports in Prettier overrides and adds several new deps/devDeps (including @trivago/prettier-plugin-sort-imports, @stylistic/eslint-plugin, @swc/core, @swc/jest, @total-typescript/ts-reset, intl-messageformat, seedrandom, @types/seedrandom, eslint-plugin-jest), and removes ts-jest. Scripts unchanged.
Rendering: SAM radius layer & renderer updates
src/client/graphics/GameRenderer.ts, src/client/graphics/layers/SAMRadiusLayer.ts
Adds exported SAMRadiusLayer implementing Layer (overlay canvas, tick/redraw, draws dashed yellow radius using defaultSamRange). Updates GameRenderer imports and constructor/fields to readonly, initializes a SAMRadiusLayer instance (but does not add it to the layers array in this patch), adjusts emoji table init and UILayer constructor usage.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Frame as "Frame tick"
  participant GameRenderer
  participant SAMRadiusLayer
  participant GameView
  participant TransformHandler
  participant OverlayCanvas as "Overlay Canvas"
  participant MainCanvas as "Main Canvas"

  Note over GameRenderer,SAMRadiusLayer: setup
  GameRenderer->>SAMRadiusLayer: new(game, eventBus, transformHandler)
  GameRenderer->>SAMRadiusLayer: init()
  SAMRadiusLayer->>OverlayCanvas: create canvas + getContext('2d')
  SAMRadiusLayer->>SAMRadiusLayer: redraw() — populate samLaunchers

  loop per frame
    Frame->>GameRenderer: tick frame
    GameRenderer->>SAMRadiusLayer: tick()
    SAMRadiusLayer->>GameView: updatesSinceLastTick()
    SAMRadiusLayer->>SAMRadiusLayer: update samLaunchers, set needsRedraw
    alt needsRedraw or transform changed
      SAMRadiusLayer->>SAMRadiusLayer: redraw() — draw dashed/yellow circles
    end
    GameRenderer->>SAMRadiusLayer: renderLayer(mainCtx)
    SAMRadiusLayer->>MainCanvas: draw OverlayCanvas (centered)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Feature - Frontend, UI/UX

Suggested reviewers

  • evanpelle
  • drillskibo
  • scottanderson

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "SAM Launcher Defense Radius" succinctly and accurately describes the primary change — adding a visible SAM launcher defense radius to the UI — and is concise and specific enough for teammates scanning PR history.
Description Check ✅ Passed The pull request description is directly related to the changeset, includes a screenshot of the UI change, and lists checklist items confirming tests and i18n updates, so it meets the lenient description requirements.

Poem

Bright circles bloom on overlayed skies,
Yellow dashed rings mark watchful eyes.
Imports tidy, layers newly born,
Canvas echoes at early morn.
Small changes stack — the game adorns.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@CLAassistant
Copy link

CLAassistant commented Sep 1, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
7 out of 25 committers have signed the CLA.

✅ DevelopingTom
✅ Baguette8ot
✅ woodydrn
✅ evanpelle
✅ abdallahbahrawi1
✅ TheGiraffe3
✅ Boostry123
❌ scottanderson
❌ pierrebrtr
❌ Aotumuri
❌ TylerHanavan
❌ dependabot[bot]
❌ djmrFunnyMan
❌ Kipstz
❌ Cameron Clark
❌ TLS15
❌ Killersoren
❌ fantom845
❌ ElMelchizedek
❌ PilkeySEK
❌ mokizzz
❌ Bornasm
❌ wnusair
❌ VariableVince
❌ aaa4xu


Cameron Clark seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (9)
package.json (1)

36-36: Import-sorting plugin is added but not actually used; consider removing or enabling it globally (pick one).

Right now, "@trivago/prettier-plugin-sort-imports" is only installed but not referenced in root plugins. Also, the Dockerfile override in .prettierrc won’t use it (that plugin doesn’t handle Dockerfiles). Keep just one import sorter to avoid churn with "prettier-plugin-organize-imports".

Option A — remove unused plugin:

-    "@trivago/prettier-plugin-sort-imports": "^5.2.2",

Option B — switch to trivago plugin globally (and drop organize-imports to avoid conflicts):

   "devDependencies": {
+    "@trivago/prettier-plugin-sort-imports": "^5.2.2",
     "prettier": "^3.5.3",
-    "prettier-plugin-organize-imports": "^4.1.0",

…and in .prettierrc root:

-  "plugins": ["prettier-plugin-organize-imports", "prettier-plugin-sh"]
+  "plugins": ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-sh"],
+  "importOrder": ["^@?(\\w|/)", "^\\.", "^\\u0000"], 
+  "importOrderSeparation": true,
+  "importOrderSortSpecifiers": true
.prettierrc (1)

12-12: Wrong plugin for Dockerfile; use a Dockerfile formatter plugin instead.

"@trivago/prettier-plugin-sort-imports" won’t parse Dockerfiles. If the intent is to format Dockerfiles, use "prettier-plugin-docker".

Apply:

   {
     "files": "Dockerfile",
     "options": {
-      "plugins": ["@trivago/prettier-plugin-sort-imports"]
+      "plugins": ["prettier-plugin-docker"]
     }
   }

And add the dependency:

   "devDependencies": {
+    "prettier-plugin-docker": "^0.2.0",
   }
src/client/graphics/GameRenderer.ts (1)

203-203: Constructor seems over-injected; SAMRadiusLayer doesn’t use eventBus.

Trim the dependency to reduce coupling.

-  const samRadiusLayer = new SAMRadiusLayer(game, eventBus, transformHandler);
+  const samRadiusLayer = new SAMRadiusLayer(game, transformHandler);

(See the matching constructor change in SAMRadiusLayer.ts below.)

src/client/graphics/layers/SAMRadiusLayer.ts (6)

17-30: Offscreen canvas sizing: watch out for memory and stale dimensions.

Sizing to full map once can be heavy on large maps and won’t react if map size changes. Consider lazy (re)size on first redraw and when map dims change.

-  ) {
-    this.canvas = document.createElement("canvas");
+  ) {
+    this.canvas = document.createElement("canvas");
     const ctx = this.canvas.getContext("2d");
     if (!ctx) {
       throw new Error("2d context not supported");
     }
     this.context = ctx;
-    this.canvas.width = this.game.width();
-    this.canvas.height = this.game.height();
+    // Defer sizing until first redraw to avoid allocating huge buffers too early.

And in redraw():

   redraw() {
+    // Ensure canvas matches current map size
+    if (this.canvas.width !== this.game.width() || this.canvas.height !== this.game.height()) {
+      this.canvas.width = this.game.width();
+      this.canvas.height = this.game.height();
+    }

32-36: Comment says “listen for updates” but no subscriptions exist.

Either wire an event, or reword the comment.

-  init() {
-    // Listen for game updates to detect SAM launcher changes
-    this.redraw();
-  }
+  init() {
+    // Initial draw; subsequent changes detected in tick()
+    this.redraw();
+  }

41-77: Avoid redrawing on pan/zoom; it’s unnecessary work.

Geometry doesn’t change with transform; only placement does. Keep redraws for SAM add/remove only.

-    // Redraw if transform changed or if we need to redraw
-    if (this.transformHandler.hasChanged() || this.needsRedraw) {
+    // Redraw only when content changed
+    if (this.needsRedraw) {
       this.redraw();
       this.needsRedraw = false;
     }

93-99: Drop redundant isActive filter.

GameView.units(UnitType.SAMLauncher) already returns active units.

-    const samLaunchers = this.game.units(UnitType.SAMLauncher).filter((unit) => unit.isActive());
+    const samLaunchers = this.game.units(UnitType.SAMLauncher);

106-141: Range source: prefer per-unit value, fallback to config.

If SAM range can vary (upgrades, tech, buffs), read from the unit first and default to config to keep visuals correct.

-    const radius = this.game.config().defaultSamRange(); // 70 pixels
+    const radius =
+      // @ts-expect-error optional property if available
+      (sam as any).range?.() ??
+      this.game.config().defaultSamRange();

Would you confirm whether UnitView exposes a range for SAMs?


1-21: Constructor: remove unused eventBus to simplify.

eventBus is not used; drop it here and at call site.

-import type { EventBus } from "../../../core/EventBus";
@@
-  constructor(
-    private readonly game: GameView,
-    private readonly eventBus: EventBus,
-    private readonly transformHandler: TransformHandler,
-  ) {
+  constructor(
+    private readonly game: GameView,
+    private readonly transformHandler: TransformHandler,
+  ) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1ae7ebc and dd82cfc.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • .prettierrc (1 hunks)
  • package.json (1 hunks)
  • src/client/graphics/GameRenderer.ts (3 hunks)
  • src/client/graphics/layers/SAMRadiusLayer.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/client/graphics/layers/SAMRadiusLayer.ts (3)
src/client/graphics/layers/Layer.ts (1)
  • Layer (1-7)
src/core/game/GameView.ts (3)
  • GameView (364-696)
  • unit (576-578)
  • UnitView (47-178)
src/client/graphics/TransformHandler.ts (1)
  • TransformHandler (15-296)
src/client/graphics/GameRenderer.ts (1)
src/client/graphics/layers/SAMRadiusLayer.ts (1)
  • SAMRadiusLayer (11-141)
🔇 Additional comments (3)
src/client/graphics/GameRenderer.ts (2)

27-27: LGTM: import is correct and scoped.


237-237: Good layer ordering.

Placing the radius after StructureLayer (and before icons/units) gives clear visuals without covering units.

src/client/graphics/layers/SAMRadiusLayer.ts (1)

79-87: Verify drawImage offset assumptions.

The -width/2, -height/2 offset assumes world origin is map center. If origin is top-left in world space, this should be (0, 0) instead. Please confirm visually at extreme zoom/pan.

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 1, 2025
@BrewedCoffee
Copy link

Would it make sense to add this to the same view as hovering over SAM structures?

@evanpelle evanpelle dismissed coderabbitai[bot]’s stale review September 4, 2025 02:44

The merge-base changed after approval.

@evanpelle evanpelle requested a review from a team as a code owner September 4, 2025 02:44
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
package.json (3)

32-36: Avoid running two import-sorting plugins (conflicts/churn).

You're adding @trivago/prettier-plugin-sort-imports while prettier-plugin-organize-imports is already present. Running both causes unstable diffs. Pick one (recommend the Trivago plugin) and drop the other.

Apply this diff to remove organize-imports:

-    "prettier-plugin-organize-imports": "^4.1.0",

122-122: intl-messageformat added—good for i18n.

Confirm tree-shaking and that translateText() uses a single shared formatter instance to avoid allocations per render.


128-128: seedrandom added—prefer native crypto when possible.

If you need reproducible seeds, seedrandom is fine. For non-deterministic RNG, use crypto.getRandomValues().

src/client/graphics/GameRenderer.ts (2)

232-234: Good callout on grouping by shouldTransform.

The comment helps avoid excessive save/restore. Consider batching all transformed layers together explicitly.


60-61: Typo in comment.

"dcoument" → "document".

-  // TODO maybe append this to dcoument instead of querying for them?
+  // TODO maybe append this to document instead of querying for them?
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b3cceb and 68d5399.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • .prettierrc (1 hunks)
  • package.json (4 hunks)
  • src/client/graphics/GameRenderer.ts (9 hunks)
  • src/client/graphics/layers/SAMRadiusLayer.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .prettierrc
  • src/client/graphics/layers/SAMRadiusLayer.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-09T02:20:43.637Z
Learnt from: VariableVince
PR: openfrontio/OpenFrontIO#1110
File: src/client/Main.ts:293-295
Timestamp: 2025-06-09T02:20:43.637Z
Learning: In src/client/Main.ts, during game start in the handleJoinLobby callback, UI elements are hidden using direct DOM manipulation with classList.add("hidden") for consistency. This includes modals, buttons, and error divs. The codebase follows this pattern rather than using component APIs for hiding elements during game transitions.

Applied to files:

  • src/client/graphics/GameRenderer.ts
🧬 Code graph analysis (1)
src/client/graphics/GameRenderer.ts (7)
src/client/graphics/layers/SAMRadiusLayer.ts (1)
  • SAMRadiusLayer (11-141)
src/client/graphics/layers/UILayer.ts (1)
  • UILayer (27-370)
src/core/game/GameView.ts (1)
  • GameView (364-696)
src/core/EventBus.ts (1)
  • EventBus (8-46)
src/client/graphics/TransformHandler.ts (1)
  • TransformHandler (15-296)
src/client/graphics/UIState.ts (1)
  • UIState (1-3)
src/client/graphics/layers/Layer.ts (1)
  • Layer (1-7)
🔇 Additional comments (4)
package.json (2)

67-67: Install missing dependency & re-run the eslint-plugin-jest check

ESLint aborted loading eslint.config.js: "eslint-config-prettier" not found, so the compatibility check did not run.

Actions:

  • Install the missing package: npm install --save-dev eslint-config-prettier (or pnpm/yarn equivalent)
  • Locate config files: rg -n --hidden --glob '!node_modules' 'eslint.config|.eslintrc'
  • Re-run and confirm jest rules load (use a real source file):
    npx -y eslint --print-config <path/to/source-file> | head -n 60
    npx -y eslint --print-config <path/to/source-file> | rg -n 'jest' -C2

If jest rules are not present after fixing the import, check that eslint-plugin-jest v29 supports ESLint 9 flat config and update the config format accordingly.


33-35: Ensure Jest uses @swc/jest and remove ts-jest remnants

  • Search output shows no "ts-jest" occurrences.
  • Action: confirm Jest config uses a transform like { "^.+\.(t|j)sx?$": "@swc/jest" } and remove any "preset": "ts-jest" or "transform" references to ts-jest. Check: jest.config.{js,ts,cjs}, package.json "jest" key, CI/test configs, and tsconfig.jest.json.
src/client/graphics/GameRenderer.ts (2)

289-299: Immutability on renderer fields—nice.

readonly on core dependencies prevents accidental reassignment and clarifies ownership.


243-243: UILayer ctor change — signature confirmed (game, eventBus)

All occurrences (src/client/graphics/GameRenderer.ts and tests/client/graphics/UILayer.test.ts) call new UILayer(game, eventBus); none pass transformHandler.

"@stylistic/eslint-plugin": "^5.2.3",
"@swc/core": "^1.13.3",
"@swc/jest": "^0.2.39",
"@total-typescript/ts-reset": "^0.6.1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Wire up ts-reset early or via tsconfig types.

@total-typescript/ts-reset only works if imported first or added to tsconfig "types".

Run:


🏁 Script executed:

#!/bin/bash
# Option A: direct import at app entry (should be first import)
rg -nP '^\s*import\s+["\']@total-typescript/ts-reset["\']' -g '!**/node_modules/**' -C2

# Option B: tsconfig types entry
fd -a tsconfig*.json | xargs -I{} rg -nP '"types"\s*:\s*\[[^\]]*"@total-typescript/ts-reset"[^\]]*\]' {}

Length of output: 68


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== A) Search for any mention of @total-typescript/ts-reset =="
rg -n --hidden --no-ignore -S "@total-typescript/ts-reset" -g '!*node_modules*' || true

echo
echo "== B) Search for import lines that import ts-reset =="
rg -n --hidden --no-ignore -S "import.*@total-typescript/ts-reset" -g '!*node_modules*' -C2 || true

echo
echo "== C) Check tsconfig*.json files for compilerOptions.types =="
files=$(fd -a tsconfig*.json || true)
if [ -z "$files" ]; then
  files=$(find . -type f -name 'tsconfig*.json' 2>/dev/null || true)
fi

if [ -z "$files" ]; then
  echo "No tsconfig*.json files found."
  exit 0
fi

for f in $files; do
  echo
  echo "=== $f ==="
  python - <<PY
import json,sys
f="$f"
try:
    j=json.load(open(f))
except Exception as e:
    print(f"{f}: json parse error: {e}")
    sys.exit(0)
co = j.get("compilerOptions",{}) or {}
types = co.get("types")
if isinstance(types, list) and "@total-typescript/ts-reset" in types:
    print(f"{f}: contains @total-typescript/ts-reset in compilerOptions.types")
else:
    print(f"{f}: does NOT contain @total-typescript/ts-reset")
ext = j.get("extends")
if ext:
    print(f"{f}: extends -> {ext}")
PY
done

Length of output: 825


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== SEARCH: any mention of @total-typescript/ts-reset =="
rg -n --hidden --no-ignore -S "@total-typescript/ts-reset" --glob '!**/node_modules/**' --glob '!.git/**' || echo "No matches found."

echo
echo "== SEARCH: direct import or require lines =="
rg -n --hidden --no-ignore -S "^\s*(import\s+['\"]@total-typescript/ts-reset['\"]|require\(['\"]@total-typescript/ts-reset['\"]\))" --glob '!**/node_modules/**' --glob '!.git/**' -C2 || echo "No direct import/require found."

echo
echo "== FIND: tsconfig*.json files =="
tsfiles=$(find . -type f -name 'tsconfig*.json' -print 2>/dev/null || true)
if [ -z "$tsfiles" ]; then
  echo "No tsconfig*.json files found."
  exit 0
fi

for f in $tsfiles; do
  echo
  echo "=== $f ==="
  echo "--- head (first 200 lines) ---"
  sed -n '1,200p' "$f" || true
  echo "--- contains literal @total-typescript/ts-reset? ---"
  rg -n "@total-typescript/ts-reset" "$f" || echo "not found"
  echo "--- types array (if any) ---"
  rg -n '"types"\s*:\s*\[[^\]]*\]' "$f" -n -C1 || echo "no types array found"
done

Length of output: 1843


Wire up @total-typescript/ts-reset — import first or add to tsconfig types

  • Observed: no import of "@total-typescript/ts-reset" in the repo; tsconfig.json (root) has no "types"; tsconfig.jest.json has "types": ["jest","node"] and extends ./tsconfig.json.
  • Action (pick one):
    • Import it as the very first runtime import in your app entry (e.g. add at top of src/index.ts or src/main.ts): import '@total-typescript/ts-reset';
    • Or add "@total-typescript/ts-reset" to compilerOptions.types in tsconfig.json — and also add it to tsconfig.jest.json (it currently overrides types), or remove the override so the base applies.
  • Files to change: tsconfig.json, tsconfig.jest.json, and your app entry file.
🤖 Prompt for AI Agents
In package.json around line 35, the repo added the dependency
"@total-typescript/ts-reset" but it's not wired in; either import it as the
first runtime import in your app entry (e.g., add import
'@total-typescript/ts-reset'; at the very top of src/index.ts or src/main.ts) or
register it in TypeScript config by adding "@total-typescript/ts-reset" to
compilerOptions.types in tsconfig.json and also ensure tsconfig.jest.json either
includes that type or stops overriding types (or add it there as well); update
tsconfig.json, tsconfig.jest.json, and the app entry file accordingly so the
reset is applied at runtime or compile-time.

emojiTable.transformHandler = transformHandler;
emojiTable.game = game;
emojiTable.initEventBus(eventBus);
emojiTable.init(transformHandler, game, eventBus);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Guard against null: emojiTable.init may throw if element missing.

The query may return null; calling init unconditionally can crash.

Apply:

-  emojiTable.init(transformHandler, game, eventBus);
+  if (emojiTable instanceof EmojiTable) {
+    emojiTable.init(transformHandler, game, eventBus);
+  } else {
+    console.error("EmojiTable element not found in the DOM");
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
emojiTable.init(transformHandler, game, eventBus);
if (emojiTable instanceof EmojiTable) {
emojiTable.init(transformHandler, game, eventBus);
} else {
console.error("EmojiTable element not found in the DOM");
}
🤖 Prompt for AI Agents
In src/client/graphics/GameRenderer.ts around line 65, calling
emojiTable.init(transformHandler, game, eventBus) unconditionally can throw if
the queried DOM element is null; modify the code to first obtain the element
reference, check for null/undefined, and only call emojiTable.init when the
element exists; if the element is missing, log a warning or early-return so
initialization is skipped safely (or provide a fallback element) to prevent
runtime crashes.

headsUpMessage.game = game;

const structureLayer = new StructureLayer(game, eventBus, transformHandler);
const samRadiusLayer = new SAMRadiusLayer(game, eventBus, transformHandler);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

SAMRadiusLayer is never rendered (not added to layers).

You construct samRadiusLayer but don’t include it in layers, so the radius never shows.

Add it just before UILayer so it draws beneath UI but above FX/units as desired:

   new UnitLayer(game, eventBus, transformHandler),
   new FxLayer(game),
+  samRadiusLayer,
   new UILayer(game, eventBus),

If you prefer the radii under units, place it before UnitLayer instead.

Also applies to: 235-245

🤖 Prompt for AI Agents
In src/client/graphics/GameRenderer.ts around line 203 (and similarly for the
block at 235-245), you instantiate samRadiusLayer but never add it to the
renderer layers array so it never gets drawn; insert the samRadiusLayer into the
layers list just before the UILayer creation so it renders beneath UI but above
FX/units (or, if you want radii beneath units, insert it before the UnitLayer
instead). Ensure the layers array/order is updated accordingly and remove any
unused local variable warnings if needed.

@github-project-automation github-project-automation bot moved this from Triage to Development in OpenFront Release Management Sep 11, 2025
@TheGiraffe3 TheGiraffe3 linked an issue Sep 21, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Development
Development

Successfully merging this pull request may close these issues.

SAM range upgrade : updated feature