Skip to content

Conversation

Mikesteam1234
Copy link

@Mikesteam1234 Mikesteam1234 commented Aug 30, 2025

…ffects keybind related actions. Actions such as Escape and Performance overlay remain as physical key presses.

Description:

This PR fixes #1071 in which the physical key code was used over the key itself. The previous behavior resulted in issues when using keyboard layouts outside of the standard such as AZERTY.

The ideal fix would utilize a command pattern and some central manager that would route key presses. This PR is a half step towards that methodology as a quick fix for the issue described.

This approach should also respect user keybinds already in production -- converting their 'physical keys' to 'digital.'

All tests pass:
image

Manually tested behavior on local build, behaves as expected using QWERTY and AZERTY.

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:

Mikesteam1234

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 <662325+scottanderson@users.noreply.github.com>
…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 <59177241+drillskibo@users.noreply.github.com>
## 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 <59177241+drillskibo@users.noreply.github.com>
## 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 <59177241+drillskibo@users.noreply.github.com>
…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: on-headers@1.1.0 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: on-headers@1.1.0 (<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] <support@github.com>
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 <59177241+drillskibo@users.noreply.github.com>
## 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 <59177241+drillskibo@users.noreply.github.com>
## 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 <662325+scottanderson@users.noreply.github.com>
Co-authored-by: Drills Kibo <59177241+drillskibo@users.noreply.github.com>
## 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 <662325+scottanderson@users.noreply.github.com>
## 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
evanpelle and others added 18 commits August 24, 2025 16:43
## Description:

If the translation key isn't found for a pattern, show just the pattern
key, not the entire translation key. Since patterns will be added
frequently.

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

Fix color assignment crashing squad games.

For squad games, teams are assigned 1,2,3, etc. So the ColorAllocator
cannot find them and throws an exception.

## 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
…ontio#1889)

## Description:

When emoji is sent to oneself, it triggers: Cannot send emoji to
oneself: ${this}, because the canSendEmoji wasn't checking if it was
itself.

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

Bug fix: cities and ports would only connect to factories owned by the
current player, ignoring those belonging to other players.

This update makes the player ID optional when searching for nearby
units: if no player ID is provided, unit ownership is disregarded,
allowing connections to all factories regardless of ownership.
## 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
The map is very large and the game lagged a lot on this map during
playtests. So remove it from public lobbies.

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

evan
## Description:

Fix an eslint failure blocking PRs from being merged.

## 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#1922, the trainwreck bug.

## 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
The territory modal was opening on page load, this has it not open on
page load, but refresh the button on onUserMe().

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

evan
Fix a bug introduced by an optimization that caused some incoming nukes
to be ignored. As a result, long-distance nukes could evade in-range
SAM.

Changes:
Replaced the ignored nukes list with a list of precomputed nukes.
For incoming long-distance nukes, the interception tile is now computed
in advance.
When the nuke enters range, the precomputed interception tile is used
for interception.

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

IngloriousTom

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
## Description:

This PR adds a new northern hemisphere map (2000x2000 pixels) using a
pierce quincuncial projection. It has 46 nations and 16 new flags. See
openfrontio#827 for original PR.

<img width="1440" height="800" alt="Screen Shot 2025-08-13 at 7 21 34
PM"
src="https://github.com/user-attachments/assets/8668c59c-ab6c-4242-845c-8b352265805c"
/>
<img width="1440" height="800" alt="Screen Shot 2025-08-13 at 7 22 24
PM"
src="https://github.com/user-attachments/assets/99be8a1e-ceb6-4376-a2d2-fba5c9bd93e2"
/>
<img width="1440" height="800" alt="Screen Shot 2025-08-13 at 7 22 50
PM"
src="https://github.com/user-attachments/assets/9b527be1-05ed-4881-aec3-2919e204b020"
/>
<img width="1440" height="801" alt="Screen Shot 2025-08-13 at 7 22 59
PM"
src="https://github.com/user-attachments/assets/545eff17-4aa5-447f-b0eb-d7dc32eca613"
/>

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

---------

Co-authored-by: Lucas Michaud <Lucasmichaud1@gmail.com>
Co-authored-by: Lucas Michaud <45228097+LucasMichaud@users.noreply.github.com>
Co-authored-by: TheGiraffe3 <TheGiraffe3@users.noreply.github.com>
Co-authored-by: Drills Kibo <59177241+drillskibo@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
## Description:

Move `structureSpawnTileValue()` into its own file, as
`FakeHumanExecution.ts` was getting quite large.

## 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#201 by adding the ability for nations to build SAM launchers.

<img width="888" height="625" alt="image"
src="https://github.com/user-attachments/assets/b07f1b4e-d022-4674-b842-bc8b4247825d"
/>

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

Nations build defense posts. Fixes openfrontio#1854.

<img width="259" height="383" alt="image"
src="https://github.com/user-attachments/assets/aee75fd3-f52e-47d8-b47f-b192b8aaa69b"
/>

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

Nations will now send emoji when declining assistance requests.

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

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
…ffects keybind related actions. Actions such as Escape and Performance overlay remain as physical key presses.
Copy link
Contributor

coderabbitai bot commented Aug 30, 2025

Walkthrough

Reworked keyboard input handling to use event.key values, introduced a centralized Action enum and default keybind map, wired settings UI to those defaults, and added user override merging from localStorage. Updated keybind capture to store/display keys, and adjusted modifier handling and logging accordingly.

Changes

Cohort / File(s) Summary
Input actions and defaults
src/client/utilities/InputMap.ts
Added Action enum and ActionKeybindMapDefaults map centralizing default bindings.
Input handling logic
src/client/InputHandler.ts
Switched detection to event.key, normalized overrides from localStorage, merged with defaults, added camelCase action-name helper, simplified modifier checks to Control/Shift, and updated debug logs.
Settings UI defaults
src/client/UserSettingModal.ts
Replaced hard-coded defaultKey strings with ActionKeybindMapDefaults lookups for all listed actions.
Keybind capture component
src/client/components/baseComponents/setting/SettingKeybind.ts
Now captures and emits KeyboardEvent.key instead of code for bound value.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant DOM as Browser
  participant SettingKeybind
  participant UserSettingModal
  participant LocalStorage as localStorage
  participant InputHandler
  participant Game as GameEvents

  rect rgb(245,248,255)
    note over SettingKeybind,UserSettingModal: Bind/Change key
    User->>DOM: Press a key
    DOM-->>SettingKeybind: keydown (key)
    SettingKeybind->>SettingKeybind: set value = event.key
    SettingKeybind-->>UserSettingModal: dispatch "change" { value: key }
    UserSettingModal->>LocalStorage: save settings.keybinds
  end

  rect rgb(244,255,245)
    note over InputHandler: Initialize active keybinds
    InputHandler->>InputHandler: build defaults from ActionKeybindMapDefaults
    InputHandler->>LocalStorage: read settings.keybinds
    LocalStorage-->>InputHandler: overrides (keys normalized)
    InputHandler->>InputHandler: merge overrides into active map
  end

  rect rgb(255,249,240)
    note over InputHandler,Game: Runtime key handling (uses event.key)
    User->>DOM: Press key(s)
    DOM-->>InputHandler: keydown (key)
    InputHandler->>InputHandler: match key against active map<br/>(Control/Shift as modifiers)
    alt matched action
      InputHandler-->>Game: emit Action event
    else no match
      InputHandler-->>InputHandler: ignore
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Use code for detection and key for display [#1071] Detection now uses event.key; UI capture and storage also use key, not code. Physical key consistency across layouts is not preserved.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Add Action enum and ActionKeybindMapDefaults (src/client/utilities/InputMap.ts) Centralizing actions/defaults is not requested by #1071, which focuses on code vs key usage behavior.
Merge user overrides from localStorage and normalize values (src/client/InputHandler.ts) Persistence/normalization logic extends beyond the code-vs-key requirement.
Introduce convertToCamelCase for action-name mapping (src/client/InputHandler.ts) Name-shaping helper is unrelated to the issue’s objective.
Replace hard-coded defaultKey strings with dynamic lookups (src/client/UserSettingModal.ts) Refactoring defaults source is not part of the specified behavior change for #1071.

Poem

New keys dance in the night, tap-tap they say,
A map of actions leads the play.
Defaults gather, user wills blend,
Yet codes are lost around the bend—
Someday, code to steer, key to display.
For now, the letters have their way. 🎹✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/client/components/baseComponents/setting/SettingKeybind.ts (1)

73-91: Stop propagation and normalize keys for consistency.

  • Without stopPropagation, Escape while capturing can close the modal.
  • Normalize single-letter keys to lowercase to match InputHandler expectations and avoid accidental Shift+letter producing uppercase bindings.
  • Ignore "Dead"/"Unidentified" keys to avoid unusable bindings.
   private handleKeydown(e: KeyboardEvent) {
     if (!this.listening) return;
-    e.preventDefault();
+    e.preventDefault();
+    e.stopPropagation();
 
-    const { key } = e;
+    const { key } = e;
+    if (key === "Dead" || key === "Unidentified") return;
-    this.value = key;
+    const normalized =
+      key.length === 1 ? key.toLowerCase() : (key === "Spacebar" ? " " : key);
+    this.value = normalized;
 
     this.dispatchEvent(
       new CustomEvent("change", {
-        detail: { action: this.action, value: key },
+        detail: { action: this.action, value: normalized },
         bubbles: true,
         composed: true,
       }),
     );
src/client/InputHandler.ts (3)

210-217: Shift suppression check is broken (uses ShiftLeft/Right but you add 'Shift').

You add e.key ("Shift") to activeKeys, but here you check for "ShiftLeft"/"ShiftRight". Movement won’t pause while holding Shift.

-      if (
-        this.activeKeys.has("ShiftLeft") ||
-        this.activeKeys.has("ShiftRight")
-      ) {
+      if (this.activeKeys.has("Shift")) {
         return;
       }

246-257: Minus/Equal mismatches with e.key prevent zoom hotkeys from working.

  • e.key is "-" and "="; "Minus"/"Equal" are e.code values. You’re storing e.key in activeKeys, so these never match.
  • Also ensure you add "-" and "=" to activeKeys on keydown, and delete them on keyup.
-      if (
-        this.activeKeys.has(this.keybinds.zoomOut) ||
-        this.activeKeys.has("Minus")
-      ) {
+      if (
+        this.activeKeys.has(this.keybinds.zoomOut) ||
+        this.activeKeys.has("-")
+      ) {
         this.eventBus.emit(new ZoomEvent(cx, cy, this.ZOOM_SPEED));
       }
-      if (
-        this.activeKeys.has(this.keybinds.zoomIn) ||
-        this.activeKeys.has("Equal")
-      ) {
+      if (
+        this.activeKeys.has(this.keybinds.zoomIn) ||
+        this.activeKeys.has("=")
+      ) {
         this.eventBus.emit(new ZoomEvent(cx, cy, -this.ZOOM_SPEED));
       }
-          "Minus",
-          "Equal",
+          "-",
+          "=",
-      this.activeKeys.delete(e.key);
+      this.activeKeys.delete(e.key === " " ? " " : e.key);

Also applies to: 274-296, 343-344


434-449: 'realCtrl' detection is inconsistent with e.key usage.

You never add "ControlLeft/Right" to activeKeys anymore, so realCtrl is always false. Use "Control" or just event.ctrlKey.

-      const realCtrl =
-        this.activeKeys.has("ControlLeft") ||
-        this.activeKeys.has("ControlRight");
+      const realCtrl = this.activeKeys.has("Control");
🧹 Nitpick comments (8)
src/client/UserSettingModal.ts (2)

426-426: Guard against undefined defaults in templates.

ActionKeybindMapDefaults.get(...) can return undefined; Lit will stringify it as "undefined". Add a fallback.

- defaultKey="${ActionKeybindMapDefaults.get(Action.TOGGLE_VIEW)}"
+ defaultKey="${ActionKeybindMapDefaults.get(Action.TOGGLE_VIEW) ?? ""}"

Apply the same ?? "" to all defaultKey bindings listed in this comment.

Also applies to: 439-439, 448-448, 461-461, 470-470, 483-483, 492-492, 505-505, 514-514, 523-523, 532-532, 541-541


55-71: Prevent modal-close while capturing keybinds.

Pressing Escape during a keybind capture will bubble to the modal’s Escape handler. Consider stopping propagation in the key-capture component (see SettingKeybind.ts note) or gating this handler when a capture is active.

src/client/components/baseComponents/setting/SettingKeybind.ts (1)

58-66: displayKey: unreachable 'KeyX' path after switching to e.key.

Now that we store/display e.key, strings like "KeyW" shouldn’t appear. You can remove the Key* branch or keep it only as a legacy fallback.

src/client/InputHandler.ts (3)

260-296: Key-list maintenance: include Alt/Meta if you rely on activeKeys for combos.

You add "Control" and "Shift". If future checks rely on Alt/Meta presence (similar to Shift/Control), include them here for symmetry.

         [
           this.keybinds.moveUp,
           this.keybinds.moveDown,
           this.keybinds.moveLeft,
           this.keybinds.moveRight,
           this.keybinds.zoomOut,
           this.keybinds.zoomIn,
           "ArrowUp",
           "ArrowLeft",
           "ArrowDown",
           "ArrowRight",
-          "-",
-          "=",
+          "-",
+          "=",
           this.keybinds.attackRatioDown,
           this.keybinds.attackRatioUp,
           this.keybinds.centerCamera,
           "Control",
           "Shift",
+          "Alt",
+          "Meta",
         ].includes(e.key)

335-341: Debug logging left in keyup handler.

Remove or guard behind a debug flag; this is noisy every keyup.

-      console.log(e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey);

147-168: Direction check: confirm “use key for detection” vs original issue’s “use code for detection.”

The linked issue #1071 requested physical detection (event.code) and display using key. This PR flips to key detection for most actions (Escape/perf overlay still use code). This affects migration: converting "KeyW" → "w" will not yield "z" on AZERTY, so existing users may lose expected movement until they rebind.

If the product decision is to follow the issue literally (code for detection, key for display), consider:

  • Persist codes; detect with e.code.
  • For display: try navigator.keyboard.getLayoutMap() when available; fallback to simple KeyX/DigitN → x/n mapping.
  • Provide a one-time migration screen prompting users to confirm/rebind keys after this change, rather than silent conversion.

I can draft a migration helper and a display mapper if you want.

Also applies to: 260-273, 299-341, 594-610

src/client/utilities/InputMap.ts (2)

27-42: Keep map value semantics consistent.

Most entries are e.key strings (e.g., "w"), but MODIFIER_KEY/ALT_KEY use code-like strings ("ControlLeft", "AltLeft"). This is easy to misread later. Either:

  • Store canonical e.key values ("Control", "Alt") and translate where you require side-specific checks, or
  • Clearly mark these two as code-based in the type.

Example typed approach:

type KeyBindValue =
  | string // e.key
  | "ControlLeft" | "AltLeft" | "ShiftLeft" | "MetaLeft"; // explicit code-based

1-25: Prefer explicit enum values.

Give Action members explicit string values to stabilize serialization and devtools logging.

-export enum Action {
+export enum Action {
   // View and camera controls
-  TOGGLE_VIEW,
+  TOGGLE_VIEW = "TOGGLE_VIEW",
   // ...
}
📜 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 7466642.

📒 Files selected for processing (4)
  • src/client/InputHandler.ts (5 hunks)
  • src/client/UserSettingModal.ts (13 hunks)
  • src/client/components/baseComponents/setting/SettingKeybind.ts (1 hunks)
  • src/client/utilities/InputMap.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/client/UserSettingModal.ts (1)
src/client/utilities/InputMap.ts (1)
  • ActionKeybindMapDefaults (27-42)
src/client/InputHandler.ts (1)
src/client/utilities/InputMap.ts (1)
  • ActionKeybindMapDefaults (27-42)

Comment on lines 147 to 168
initialize() {
this.keybinds = {
toggleView: "Space",
centerCamera: "KeyC",
moveUp: "KeyW",
moveDown: "KeyS",
moveLeft: "KeyA",
moveRight: "KeyD",
zoomOut: "KeyQ",
zoomIn: "KeyE",
attackRatioDown: "Digit1",
attackRatioUp: "Digit2",
boatAttack: "KeyB",
groundAttack: "KeyG",
modifierKey: "ControlLeft",
altKey: "AltLeft",
...(JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {}),
};
this.keybinds = {};
for (const [action, key] of ActionKeybindMapDefaults.entries()) {
const actionKey = this.convertToCamelCase(Action[action]);
this.keybinds[actionKey] = key;
}

const userKeybinds = JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {};

for (const [action, key] of Object.entries(userKeybinds) as [string, string][]) {

let keyToWrite = key;

if (/^Key[A-Z]$/.test(key)) {
keyToWrite = key.slice(3).toLowerCase();
} else if (/^Digit[0-9]$/.test(key)) {
keyToWrite = key.slice(5);
}

this.keybinds[action] = keyToWrite;
}

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

Harden parsing and normalization of saved keybinds.

  • JSON.parse can throw; this will break input init.
  • Normalize legacy and mixed inputs: KeyX → x, DigitN → N, Space/Spacebar → " ", single letters → lowercase.
-    const userKeybinds = JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {};
-
-    for (const [action, key] of Object.entries(userKeybinds) as [string, string][]) {
-
-      let keyToWrite = key;
-
-      if (/^Key[A-Z]$/.test(key)) {
-        keyToWrite = key.slice(3).toLowerCase();
-      } else if (/^Digit[0-9]$/.test(key)) {
-        keyToWrite = key.slice(5);
-      }
-
-      this.keybinds[action] = keyToWrite;
-    }
+    let userKeybinds: Record<string, string> = {};
+    try {
+      const raw = localStorage.getItem("settings.keybinds");
+      const parsed = raw ? JSON.parse(raw) : {};
+      if (parsed && typeof parsed === "object") {
+        userKeybinds = parsed as Record<string, string>;
+      }
+    } catch {
+      // ignore corrupt storage; keep defaults
+    }
+
+    for (const [action, key] of Object.entries(userKeybinds) as [string, string][]) {
+      let keyToWrite = key;
+      if (/^Key[A-Z]$/.test(key)) {
+        keyToWrite = key.slice(3).toLowerCase();
+      } else if (/^Digit[0-9]$/.test(key)) {
+        keyToWrite = key.slice(5);
+      } else if (key === "Space" || key === "Spacebar") {
+        keyToWrite = " ";
+      } else if (key.length === 1) {
+        keyToWrite = key.toLowerCase();
+      }
+      this.keybinds[action] = keyToWrite;
+    }
📝 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
initialize() {
this.keybinds = {
toggleView: "Space",
centerCamera: "KeyC",
moveUp: "KeyW",
moveDown: "KeyS",
moveLeft: "KeyA",
moveRight: "KeyD",
zoomOut: "KeyQ",
zoomIn: "KeyE",
attackRatioDown: "Digit1",
attackRatioUp: "Digit2",
boatAttack: "KeyB",
groundAttack: "KeyG",
modifierKey: "ControlLeft",
altKey: "AltLeft",
...(JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {}),
};
this.keybinds = {};
for (const [action, key] of ActionKeybindMapDefaults.entries()) {
const actionKey = this.convertToCamelCase(Action[action]);
this.keybinds[actionKey] = key;
}
const userKeybinds = JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {};
for (const [action, key] of Object.entries(userKeybinds) as [string, string][]) {
let keyToWrite = key;
if (/^Key[A-Z]$/.test(key)) {
keyToWrite = key.slice(3).toLowerCase();
} else if (/^Digit[0-9]$/.test(key)) {
keyToWrite = key.slice(5);
}
this.keybinds[action] = keyToWrite;
}
initialize() {
this.keybinds = {};
for (const [action, key] of ActionKeybindMapDefaults.entries()) {
const actionKey = this.convertToCamelCase(Action[action]);
this.keybinds[actionKey] = key;
}
let userKeybinds: Record<string, string> = {};
try {
const raw = localStorage.getItem("settings.keybinds");
const parsed = raw ? JSON.parse(raw) : {};
if (parsed && typeof parsed === "object") {
userKeybinds = parsed as Record<string, string>;
}
} catch {
// ignore corrupt storage; keep defaults
}
for (const [action, key] of Object.entries(userKeybinds) as [string, string][]) {
let keyToWrite = key;
if (/^Key[A-Z]$/.test(key)) {
keyToWrite = key.slice(3).toLowerCase();
} else if (/^Digit[0-9]$/.test(key)) {
keyToWrite = key.slice(5);
} else if (key === "Space" || key === "Spacebar") {
keyToWrite = " ";
} else if (key.length === 1) {
keyToWrite = key.toLowerCase();
}
this.keybinds[action] = keyToWrite;
}
🤖 Prompt for AI Agents
In src/client/InputHandler.ts around lines 147 to 168, the JSON.parse of
localStorage and the key normalization are brittle: wrap the parse in try/catch
and fall back to an empty object on error; then normalize each saved key before
assigning by handling legacy prefixes and variants—if key matches /^Key[A-Z]$/
set to the single lowercase letter, if /^Digit[0-9]$/ set to the digit, if key
equals "Space" or "Spacebar" map to " ", if key is a single alphabetic character
convert to lowercase, otherwise keep the original key; finally assign the
normalized value into this.keybinds[action] (ensuring action keys match the
camelCased action names used earlier).

@CLAassistant
Copy link

CLAassistant commented Sep 4, 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.

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


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.

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.

keyboard shortcuts: use code for detection and key for display