Commit Graph

3443 Commits

Author SHA1 Message Date
VariableVince c29fca477b Fix(HelpModal): small updates and fixes (#3473)
## Description:

- fix info icon spacing
- update multiple texts to reflect current state, rewrote
"ui_playeroverlay_desc" further for better readability
- add text for the options menu, and change their order to reflect
current button order
- add missing "Stop trading" icon, is PNG so lazy load
- remove uneccesary lazy loading for an SVG icon (rest of the SVGs
aren't lazy loaded either)

Didn't touch the rest although more incremental updates are needed
following UI and other changes.

Before:
<img width="242" height="82" alt="image"
src="https://github.com/user-attachments/assets/8f38eef6-21e7-4b18-84ef-adc4161a317f"
/>

<img width="357" height="167" alt="image"
src="https://github.com/user-attachments/assets/c6937b5c-c1b2-4560-b40b-94b24a4906cc"
/>

After:
<img width="262" height="95" alt="image"
src="https://github.com/user-attachments/assets/15c1e9f5-3e27-4f4b-8472-5bb70234ab42"
/>

<img width="345" height="203" alt="image"
src="https://github.com/user-attachments/assets/3d3fe3c5-98b2-41fb-8f79-48d02d7ecf9b"
/>

## Please complete the following:

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

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

tryout33

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-20 14:03:06 -07:00
VariableVince 54a63ac481 Could help decrease icons disappearing: Update PixiJS (#3478)
## Description:

Please put in next v30 update if possible.

Upgrade [PixiJS from 8.11.0 to their newest version
8.17.1](https://github.com/pixijs/pixijs/releases) and pixi-filters too.

This could help decrease occurance of this issue:
https://github.com/openfrontio/OpenFrontIO/issues/2147

Checked "Behavior Change" in their release notes and we aren't touched
by those. But some of the fixes, especially GC/memory leak, may help in
reducing "dissappearing structure icons". Update to destroy() now using
the new unload() could help too; we call destroy() directly on
ghoststructures and its possibly called elsewhere under the surface too.

## Please complete the following:

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

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

tryout33
2026-03-20 12:26:35 -07:00
Mattia Migliorini 2ec12f0a3a Auto-reject alliance request when transport ship is sent to target player (#3477)
## Description:

When a player sends a transport ship toward another player's territory,
any pending alliance request from the target is now automatically
rejected.
This mirrors the behavior already in place for direct attacks,
preventing a player from exploiting a pending alliance request while
launching a naval invasion.

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

deshack_82603
2026-03-20 10:56:36 -07:00
dependabot[bot] e02553c9b8 Bump flatted from 3.3.3 to 3.4.2 in the npm_and_yarn group across 1 directory (#3476)
Bumps the npm_and_yarn group with 1 update in the / directory:
[flatted](https://github.com/WebReflection/flatted).

Updates `flatted` from 3.3.3 to 3.4.2
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/WebReflection/flatted/commit/3bf09091c3562e17a0647bc06710dd6097079cf7"><code>3bf0909</code></a>
3.4.2</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/885ddcc33cf9657caf38c57c7be45ae1c5272802"><code>885ddcc</code></a>
fix CWE-1321</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/0bdba705d130f00892b1b8fcc80cf4cdea0631e3"><code>0bdba70</code></a>
added flatted-view to the benchmark</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/2a02dce7c641dec31194c67663f9b0b12e62da20"><code>2a02dce</code></a>
3.4.1</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/fba4e8f2e113665da275b19cd0f695f3d98e9416"><code>fba4e8f</code></a>
Merge pull request <a
href="https://redirect.github.com/WebReflection/flatted/issues/89">#89</a>
from WebReflection/python-fix</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/5fe86485e6df7f7f34a07a2a85498bd3e17384e7"><code>5fe8648</code></a>
added &quot;when in Rome&quot; also a test for PHP</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/53517adbefe724fe472b2f9ebcdb01910d0ae3f0"><code>53517ad</code></a>
some minor improvement</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/b3e2a0c387bf446435fec45ad7f05299f012346f"><code>b3e2a0c</code></a>
Fixing recursion issue in Python too</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/c4b46dbcbf782326e54ea1b65d3ebb1dc7a23fad"><code>c4b46db</code></a>
Add SECURITY.md for security policy and reporting</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/f86d071e0f70de5a7d8200198824a3f07fc9c988"><code>f86d071</code></a>
Create dependabot.yml for version updates</li>
<li>Additional commits viewable in <a
href="https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.2">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 22:27:38 -07:00
VariableVince 8e6c0c1132 Chore:Deprecation of Node 20: migrate actions in workflows to Node 24 versions (#3460)
## Description:

Node 20 will reach EOL in April 2026. Node.js 20 actions are deprecated
and will be forced to run on Node.js 24 starting June 2, 2026:
https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

Update our workflows in this PR.

- For _deployment-action_ and _deployment-status_: stop using these and
. They seem quite unmaintained which could pose risks and there is no
Node 24 version yet:
https://github.com/chrnorm/deployment-action/issues/93 and
https://github.com/chrnorm/deployment-status/issues/53. It will probably
be updated to Node 24, but why wait if we don't actually need to be
dependent on them per se.

- Instead of the above, use actions/github-script@v8 with default API.
Maybe a bit more maintainance work, if any, but better than to be
dependent on unmaintained outside actions. For reference see
https://docs.github.com/en/rest/deployments/deployments?apiVersion=2026-03-10#create-a-deployment

- For _auto-author-assign_, use v3.0.1
(4d585cc37690897bd9015942ed6e766aa7cdb97f). From v3.0.0 it uses Node 24:
https://github.com/toshimaru/auto-author-assign/releases

- For _stale_, use v10.2.0 (b5d41d4e1d5dceea10e7104786b73624c18a190f).
From v10.0.0 it uses Node 24: https://github.com/actions/stale/releases

- For other actions, use their appropriate version for Node 24.

- Tested all with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true

## Please complete the following:

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

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

tryout33
2026-03-19 21:32:32 -07:00
Mattia Migliorini 5562993042 Highlight own player name and team in lobby modal (#3468)
## Description:

> I always lose track of myself in lobbies, could our names be bolded or
even our entire team bolded for ease of readability?

This PR highlights own username and own team in lobby modal, to make it
easy for players to track themselves.
It's also useful when your username gets changed by the profanity
filter.

Based on [this Discord
suggestion](https://discord.com/channels/1284581928254701718/1484056268355145778)

### Screenshots

FFA (Public):

<img width="916" height="805" alt="image"
src="https://github.com/user-attachments/assets/5d769b48-3217-495c-bdcd-9a61fd05cd8f"
/>

Teams (Public):

<img width="912" height="798" alt="image"
src="https://github.com/user-attachments/assets/0b3966f9-4094-4dfe-a11f-ce225824690a"
/>

FFA (Private):

<img width="912" height="798" alt="image"
src="https://github.com/user-attachments/assets/21ac32ac-1fd0-4318-b2c8-44f3a2756e2e"
/>

<img width="906" height="800" alt="image"
src="https://github.com/user-attachments/assets/7530c4a2-3bc7-4b24-828d-766d65b85f89"
/>

Teams (Private):

<img width="907" height="799" alt="image"
src="https://github.com/user-attachments/assets/c8773fb8-5015-4247-8fde-4628f0850660"
/>

<img width="910" height="800" alt="image"
src="https://github.com/user-attachments/assets/15c56a54-ffea-45ef-a86f-1a8be6995e1d"
/>


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

deshack_82603
2026-03-19 15:58:06 -07:00
Ralfi Salhon 015e3c7d19 feat: Attacking Troops Overlay (#3427)
## Description:

https://troop-advantage-layer.openfront.dev/

Hey OpenFront dev team, I've been really enjoying the game, and the
v0.30 changes have felt great so far. Happy to start contributing!

This PR introduces `AttackingTroopsOverlay`, a layer that renders live
attacker vs. defender troop counts directly on active front lines.
Players can immediately gauge combat strength without leaving the map
view.


![troop-advantage-layer](https://github.com/user-attachments/assets/9e862812-84b4-46cb-a0c6-65fa50320198)

A recent change updates the layer to just the # of attackers and a
symbol for attack/defence:

![visual-front-line](https://github.com/user-attachments/assets/46bc7117-2314-44c9-96fc-8a7e9c6ab5cd)

Left: Perspective of Anon 667 (Blue) | Right: Perspective of Anon332
(Red)

![ezgif-6261e6669d6b972b](https://github.com/user-attachments/assets/734d90c1-8f22-44dc-8f2f-b22e46676f46)

**How it works:**
- Attacker count shown for ground invasions. When attacking, your troop
count will display amber for disadvantageous, and green for advantageous
battles. When defending, the enemy troop count will switch to red if you
are at a severe disadvantage.
- Label position recalculates every tick at 200ms, tracking the front
line as it moves.
- Automatically hidden during Terrain view (spacebar)
- Labels clean up when an attack ends or its target becomes invalid

**Settings:** An "Attacking Troops Overlay" toggle is added to Settings,
enabled by default.
--> the screenshot is old, but the text has been updated
<img width="448" height="410" alt="Settings toggle"
src="https://github.com/user-attachments/assets/2df8ec7a-3f77-48b7-a9b5-ee4a6eed0412"
/>

## Checklist

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

## Discord
Radyus
2026-03-19 15:04:33 -07:00
RickD004 755e7b76cc Expand Aegean Map for balancing purposes (#3459)
## Description:

Expands the Aegean map to the left. Currently the 2 major landmasses are
unbalanced, which causes the eastern side to almost always win, both in
FFA and team games.

Original Width: 1600px | New Width=1700px

Also adds more nations / NPCs in the Greek side to create more balance
with the Turkish side, aswell as in the islands, to compensate for the
lack of bots / tribes spawning in there, to boost early island gameplay
and fasten games.

<img width="355" height="415" alt="image"
src="https://github.com/user-attachments/assets/066d86cd-5a6b-4a07-bfa4-264b7ef82a3c"
/>


## Please complete the following:

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

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

tri.star1011
2026-03-19 14:57:05 -07:00
Aotumuri f39f3b8d1c mls (v4.18) (#3470)
## Description:

mls for v30
Version identifier within MLS: 4.18

## Please complete the following:

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

## Please put your Discord username so you can be contacted if a bug or
regression is found:
aotumuri
2026-03-19 14:51:52 -07:00
FloPinguin 4eb570fb8b Remove modifiers from normal FFA/Team games (And increase chance of gold multiplier for special games, decrease random spawn) 🎲 (#3471)
## Description:

Normal (FFA and Team) public games no longer roll random modifiers.
Special games remain fully unaffected and continue to use random
modifiers as before.

I also increased the gold multiplier ticket count in the special
modifier pool from 1 to 4 because of player feedback.

Edit: And because I saw complaints of too much random spawn I decreased
the chance of it.

## Please complete the following:

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

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

FloPinguin
2026-03-19 14:48:17 -07:00
evanpelle 6b9603d445 Merge branch 'v30' 2026-03-18 19:29:42 -07:00
evanpelle c5dad1f850 on purchase redirect, check cosmetic param instead of pattern param v0.30.12 2026-03-18 19:27:33 -07:00
FloPinguin 951efd4591 teamGameSpawnAreas for Baikal (#3467)
## Description:

"Baikal (Nuke Wars)" has teamGameSpawnAreas (for Random Spawn), but
Baikal not. Because teamGameSpawnAreas was intended for a "Nuke Wars"
modifier. Let's add teamGameSpawnAreas also to Baikal to improve random
spawning (special rotation) a bit (until we have a better random spawn
algo).

## Please complete the following:

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

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

FloPinguin
2026-03-18 19:26:03 -07:00
FloPinguin 6a5b2089e7 teamGameSpawnAreas for Baikal (#3467)
## Description:

"Baikal (Nuke Wars)" has teamGameSpawnAreas (for Random Spawn), but
Baikal not. Because teamGameSpawnAreas was intended for a "Nuke Wars"
modifier. Let's add teamGameSpawnAreas also to Baikal to improve random
spawning (special rotation) a bit (until we have a better random spawn
algo).

## Please complete the following:

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

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

FloPinguin
2026-03-18 19:25:44 -07:00
Evan 3e7088cb2a Close join error (#3454)
## Description:

When joining a game after it fills up, the server rejects the player
join and the player leaves the lobby, but the join modal stays up.

## 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
v0.30.11
2026-03-17 19:20:13 -07:00
Evan cb7164a52f Place footer ad during spawn phase (#3458)
## Description:

Show the "footer_ad" ad type during the spawn phase.

<img width="1855" height="914" alt="Screenshot 2026-03-17 at 7 01 37 PM"
src="https://github.com/user-attachments/assets/9c4c1730-95a0-4fc7-a983-4fe625d38c80"
/>

## Please complete the following:

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

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

evan
2026-03-17 19:02:55 -07:00
FloPinguin 5b0b9dfd31 Increase spawn immunity from 30s to 45s for 5M starting gold maps 🛡️ (#3457)
## Description:

Increases the spawn immunity duration from 30s to 45s for maps with 5M
starting gold.

The previous 30s was too short - 45s gives players 15s longer than it
takes to build a SAM, allowing them to establish basic defenses before
becoming vulnerable.

## Please complete the following:

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

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

FloPinguin
2026-03-17 15:57:15 -07:00
FloPinguin afdb04ae5d Increase spawn immunity from 30s to 45s for 5M starting gold maps 🛡️ (#3457)
## Description:

Increases the spawn immunity duration from 30s to 45s for maps with 5M
starting gold.

The previous 30s was too short - 45s gives players 15s longer than it
takes to build a SAM, allowing them to establish basic defenses before
becoming vulnerable.

## Please complete the following:

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

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

FloPinguin
2026-03-17 15:56:52 -07:00
Ryan 1049b7e7dc Clan System Part 1 (#3276)
## Description:

Properly split out clantags and usernames, a clantag should not be part
of a username.

<img width="285" height="286" alt="image"
src="https://github.com/user-attachments/assets/8ac56e82-b12c-4fc0-9774-e445252a6e61"
/>

https://api.openfront.dev/game/ojkqZFb2


<img width="296" height="596" alt="image"
src="https://github.com/user-attachments/assets/85152f80-c111-4f87-b85b-8516c9c6137b"
/>


https://api.openfront.dev/game/MF32BkVc


requires;
https://github.com/openfrontio/infra/pull/264

## Please complete the following:

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

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

w.o.n
2026-03-17 15:55:47 -07:00
FloPinguin a30859d132 Fix labels in public lobby modifier display 🏷️ (#3456)
## Description:

Fixes two issues in the join lobby modal's modifier display:

1. **Starting Gold**: Label showed "Starting Gold (Millions)" with value
"5M", duplicating "millions". Now shows "Starting Gold" as the label,
keeping "5M" as the value.
2. **Disable Alliances**: Label showed "Disable Alliances" with value
"Enabled", which is confusing. Now shows "Alliances" as the label with
"Disabled" as the value.

Join Lobby Modal needs a general rework, I will probably make an 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

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

FloPinguin
2026-03-17 15:31:11 -07:00
FloPinguin 9785666b98 Fix labels in public lobby modifier display 🏷️ (#3456)
## Description:

Fixes two issues in the join lobby modal's modifier display:

1. **Starting Gold**: Label showed "Starting Gold (Millions)" with value
"5M", duplicating "millions". Now shows "Starting Gold" as the label,
keeping "5M" as the value.
2. **Disable Alliances**: Label showed "Disable Alliances" with value
"Enabled", which is confusing. Now shows "Alliances" as the label with
"Disabled" as the value.

Join Lobby Modal needs a general rework, I will probably make an 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

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

FloPinguin
2026-03-17 15:30:52 -07:00
VariableVince 9f8a2d2d84 Fix "you didn't enter the lobby in time" when device clock isn't synced (#3451)
## Description:

If the time on the local device differs from the server time, users may
see the message “You did not join the lobby on time.”

Resolve this by accounting for the time difference, reusing the logic in
`JoinLobbyModal` that was previously in `GameModeSelector`, and
centralizing it into `ServerTime.ts`.

Bug reports:
https://github.com/openfrontio/OpenFrontIO/issues/3428

https://discord.com/channels/1284581928254701718/1482511096597315815

https://discord.com/channels/1284581928254701718/1482382264011591781

Resolves #3428 

## Please complete the following:

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

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

tryout33
2026-03-17 15:21:38 -07:00
VariableVince 5c01e7a0c9 Fix: player name and location on wrong spot on the map (#3455)
## Description:

Fixes https://github.com/openfrontio/OpenFrontIO/issues/1021

Fixes issue that has been there since the beginning. Player name and
location and conquest FX (swords) not being in the right place. It can
happen at any time during a game and can be game-breaking in that
regard.

This makes it hard to find players, especially when trying to eliminate
their last few tiles on some island. So when clicking name in
leaderboard > wrong tiles. And when seeing name > above wrong tiles. Bug
report:
https://discord.com/channels/1284581928254701718/1444669324571967680

Also, when removing those last tiles, the wait time between updates of
player location can make it frustrating to find and eliminate them fast.
You need 2-3 clicks on their name in leaderboard, before finally being
moved to their current location.


**Cause:**
largestClusterBoundingBox not being changed when last attack happened in
same tick removeClusters last ran.

**Fix:** 
Also call removeClusters, and therefore update largestClusterBoundingBox
, when LastTileChange was AT lastCalc tick.

**Also:** 
Run removeClusters if player owns less than 100 tiles, don't wait for
ticksPerClusterCalc in that case. This way, sniping off the last couple
of island tiles of the player is easier. So it doesn't take 2-3 clicks
bbut just 1 click on the player name in the Leaderboard before the
camera moves to the next little island they are on. Also their last
clusters are annexed faster, only helping with the faster cleanup.
I think this is an optional to the fix in this PR, but still an
important QoL fix for sniping those last tiles quickly.

**BEFORE:**

https://github.com/user-attachments/assets/0960a4d3-7f8b-4368-9531-8244356bff17

**AFTER:** (also notice how it now just takes 1 click in the leaderboard
to immediately go to their next location, not 2-3 clicks)
https://youtu.be/qXJPekjsrP4

## Please complete the following:

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

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

tryout33
2026-03-17 14:10:11 -07:00
VariableVince 6952550014 Fix: player name and location on wrong spot on the map (#3455)
## Description:

Fixes https://github.com/openfrontio/OpenFrontIO/issues/1021

Fixes issue that has been there since the beginning. Player name and
location and conquest FX (swords) not being in the right place. It can
happen at any time during a game and can be game-breaking in that
regard.

This makes it hard to find players, especially when trying to eliminate
their last few tiles on some island. So when clicking name in
leaderboard > wrong tiles. And when seeing name > above wrong tiles. Bug
report:
https://discord.com/channels/1284581928254701718/1444669324571967680

Also, when removing those last tiles, the wait time between updates of
player location can make it frustrating to find and eliminate them fast.
You need 2-3 clicks on their name in leaderboard, before finally being
moved to their current location.


**Cause:**
largestClusterBoundingBox not being changed when last attack happened in
same tick removeClusters last ran.

**Fix:** 
Also call removeClusters, and therefore update largestClusterBoundingBox
, when LastTileChange was AT lastCalc tick.

**Also:** 
Run removeClusters if player owns less than 100 tiles, don't wait for
ticksPerClusterCalc in that case. This way, sniping off the last couple
of island tiles of the player is easier. So it doesn't take 2-3 clicks
bbut just 1 click on the player name in the Leaderboard before the
camera moves to the next little island they are on. Also their last
clusters are annexed faster, only helping with the faster cleanup.
I think this is an optional to the fix in this PR, but still an
important QoL fix for sniping those last tiles quickly.

**BEFORE:**

https://github.com/user-attachments/assets/0960a4d3-7f8b-4368-9531-8244356bff17

**AFTER:** (also notice how it now just takes 1 click in the leaderboard
to immediately go to their next location, not 2-3 clicks)
https://youtu.be/qXJPekjsrP4

## Please complete the following:

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

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

tryout33
2026-03-17 14:08:52 -07:00
VariableVince 82d0fb385d Fix "you didn't enter the lobby in time" when device clock isn't synced (#3451)
## Description:

If the time on the local device differs from the server time, users may
see the message “You did not join the lobby on time.”

Resolve this by accounting for the time difference, reusing the logic in
`JoinLobbyModal` that was previously in `GameModeSelector`, and
centralizing it into `ServerTime.ts`.

Bug reports:
https://github.com/openfrontio/OpenFrontIO/issues/3428

https://discord.com/channels/1284581928254701718/1482511096597315815

https://discord.com/channels/1284581928254701718/1482382264011591781

Resolves #3428 

## Please complete the following:

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

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

tryout33
2026-03-17 13:52:35 -07:00
evanpelle 79c3deabd8 remove spawn video ad 2026-03-17 11:40:42 -07:00
VariableVince 11e183366f Fix inverse annexation (#3448)
## Description:

An inverse annexation could happen where the small player (even with
0,01% tiles owned) could fully annex the large player.

**TL;DR:** basically wrong use of calculateBoundingBox in
surroundedBySamePlayer, feeding it all bordertiles, making enemyBox far
bigger than it actually was in some cases. Which resulted in enemyBox of
small player with two small clusters at some distance from each other,
being seen as inscribing the largest cluster of the bigger player. While
that largest cluster is actually the border tiles of the bigger player
surrounding the main cluster of the small player. Instead of an
annexation of small by bigger, small would incorrectly annex bigger
completely.

**Situation:** bigger player fully surrounds main cluster of smaller
player. Those border tiles are also the largest cluster of the bigger
player, for which surroundedBySamePlayer is called.
SurroundedBySamePlayer finds the small player as the only bordering
enemy of this cluster. Then it needs to check which of the two players
is surrounded by the other one. EnemyBox uses calculateBoundingBox with
all border tiles of the small player as argument. The small player also
has at least one seperate cluster elsewhere, could be on another island,
which count as border tiles too. The enemyBox from the main cluster of
the small player to the seperate cluster elsewhere, can be huge. Now
inscribed() is called and it determines that largest cluster box of the
bigger player (which was in fact calculated correctly, also making use
of calculateBoundingBox) is surrounded by the bigger enemyBox. And so
the small surrounded player fully annexes the bigger player.

**Fix:** instead of a global enemyBox, we only need the localEnemyBox
that touches the largest cluster of the bigger player. With that,
inscribed() can correctly conclude that largest cluster box surrounds
the localEnemyBox. As a matter of fact isSurrounded() already used the
same method to calculate its enemyBox as introduced by @scamiv for v30:
https://github.com/openfrontio/OpenFrontIO/pull/3127/changes#diff-fb1101a2b50dd7c353d082ff7a3351cff5469b8249b3ebca91c10573a3dfaaf1

- Change in PlayerExecution
- Added test NoInverseAnnexation.test.ts, which fails before and passes
after the fix

The bug was introduced in this commit 10 months ago:
https://github.com/openfrontio/OpenFrontIO/commit/c4381a9ad3828b06764ab1a21fc1514e37aacfd7

It has probably led to some weird annexations happening since then. The
bug could seemingly happen on any map. But was noted recently a few
times on square islands (Sierpinski) or maps (The Box/The Alps), where
the circumstances probably highten the chances of the bug occuring.

**Bug reports:**

https://discord.com/channels/1359946986937258015/1481916231689703477/1481916231689703477

https://discord.com/channels/1359946986937258015/1481916231689703477/1481963273367851030

https://discord.com/channels/1284581928254701718/1479993924432171008/1479995658302652496

https://discord.com/channels/1284581928254701718/1479993924432171008/1481865495492956182
https://discord.com/channels/1284581928254701718/1483047153571201034

**BEFORE:**

https://github.com/user-attachments/assets/4440182b-f696-45cf-bb01-b10159df8763

**AFTER**, on the same replay but with the bugfix:

https://github.com/user-attachments/assets/5f461ab2-eb62-4cc3-ae07-e2224adbbc6a

## Please complete the following:

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

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

tryout33
2026-03-17 11:15:36 -07:00
VariableVince 0dc8fbf129 Fix inverse annexation (#3448)
## Description:

An inverse annexation could happen where the small player (even with
0,01% tiles owned) could fully annex the large player.

**TL;DR:** basically wrong use of calculateBoundingBox in
surroundedBySamePlayer, feeding it all bordertiles, making enemyBox far
bigger than it actually was in some cases. Which resulted in enemyBox of
small player with two small clusters at some distance from each other,
being seen as inscribing the largest cluster of the bigger player. While
that largest cluster is actually the border tiles of the bigger player
surrounding the main cluster of the small player. Instead of an
annexation of small by bigger, small would incorrectly annex bigger
completely.

**Situation:** bigger player fully surrounds main cluster of smaller
player. Those border tiles are also the largest cluster of the bigger
player, for which surroundedBySamePlayer is called.
SurroundedBySamePlayer finds the small player as the only bordering
enemy of this cluster. Then it needs to check which of the two players
is surrounded by the other one. EnemyBox uses calculateBoundingBox with
all border tiles of the small player as argument. The small player also
has at least one seperate cluster elsewhere, could be on another island,
which count as border tiles too. The enemyBox from the main cluster of
the small player to the seperate cluster elsewhere, can be huge. Now
inscribed() is called and it determines that largest cluster box of the
bigger player (which was in fact calculated correctly, also making use
of calculateBoundingBox) is surrounded by the bigger enemyBox. And so
the small surrounded player fully annexes the bigger player.

**Fix:** instead of a global enemyBox, we only need the localEnemyBox
that touches the largest cluster of the bigger player. With that,
inscribed() can correctly conclude that largest cluster box surrounds
the localEnemyBox. As a matter of fact isSurrounded() already used the
same method to calculate its enemyBox as introduced by @scamiv for v30:
https://github.com/openfrontio/OpenFrontIO/pull/3127/changes#diff-fb1101a2b50dd7c353d082ff7a3351cff5469b8249b3ebca91c10573a3dfaaf1

- Change in PlayerExecution
- Added test NoInverseAnnexation.test.ts, which fails before and passes
after the fix

The bug was introduced in this commit 10 months ago:
https://github.com/openfrontio/OpenFrontIO/commit/c4381a9ad3828b06764ab1a21fc1514e37aacfd7

It has probably led to some weird annexations happening since then. The
bug could seemingly happen on any map. But was noted recently a few
times on square islands (Sierpinski) or maps (The Box/The Alps), where
the circumstances probably highten the chances of the bug occuring.

**Bug reports:**

https://discord.com/channels/1359946986937258015/1481916231689703477/1481916231689703477

https://discord.com/channels/1359946986937258015/1481916231689703477/1481963273367851030

https://discord.com/channels/1284581928254701718/1479993924432171008/1479995658302652496

https://discord.com/channels/1284581928254701718/1479993924432171008/1481865495492956182
https://discord.com/channels/1284581928254701718/1483047153571201034

**BEFORE:**

https://github.com/user-attachments/assets/4440182b-f696-45cf-bb01-b10159df8763

**AFTER**, on the same replay but with the bugfix:

https://github.com/user-attachments/assets/5f461ab2-eb62-4cc3-ae07-e2224adbbc6a

## Please complete the following:

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

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

tryout33
2026-03-17 11:15:18 -07:00
Evan cce46ef126 Refactor: use promises instead of callbacks for joining a game (#3452)
## Description:

Simplifies the interface a bit.

## Please complete the following:

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

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

evan
2026-03-17 10:08:30 -07:00
Evan dd2c239aa1 Have Worker rate limit ws messages (#3449)
## Description:

Prevent client from spamming ws messages before joining a game server.

## 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
v0.30.10
2026-03-16 20:45:05 -07:00
Evan 5e7317a818 Update socket rate limiting (#3447)
## Description:

On replays, there can be a burst of traffic from hashes, so instead just
have a 2MB limit per client for the entire game. Also the winner message
can be 100s of kb on a large game with many players, so now we don't
need to put a special case for that.

## Please complete the following:

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

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

evan
2026-03-16 20:26:56 -07:00
evanpelle 194a288ce1 reduce ws max size to 1 mb 2026-03-16 20:13:14 -07:00
Evan 51db6a2772 Add in game add to bottom left corner (#3446)
## Description:

Remove the header ad because that's where the player info overlay is,
and instead put it on the bottom left

Ad is not displayed on small screens.

<img width="1916" height="924" alt="Screenshot 2026-03-16 at 7 27 58 PM"
src="https://github.com/user-attachments/assets/e39c4be6-5270-4a77-bfbd-9521d15b9211"
/>

## Please complete the following:

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

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

evan
2026-03-16 19:36:02 -07:00
bijx f356f09f81 Feat: Game Speed + Pause keybinds (#3397)
## Description:

Can't tell you how many times I've been playing solo, I try to go change
the speed from `Max` to `x1` and before I've opened the speed controls
and clicked on one the AI completely wipes me. But not to worry, we now
have a pause and speed toggle up/down keybinds!


https://github.com/user-attachments/assets/48692c27-888f-40fb-837a-45e26f262441

Keybinds were added to "Menu Shortcuts" submenu:

<img width="1750" height="1099" alt="image"
src="https://github.com/user-attachments/assets/8c4500d5-f43e-4a1c-9940-04db75bf18cf"
/>

Tested on Solo, custom match, and public lobbies. Pause intent works
correctly on solo and private match (only if you are host), and neither
feature works in public matches, as expected.



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

bijx
2026-03-16 23:16:59 +00:00
FloPinguin f7e50826de Reduce spawn phase duration when random spawn is enabled ⏱️ (#3437)
## Description:

Reduces `numSpawnPhaseTurns` from 300 to 100 (matching singleplayer
duration) when random spawn is active. Since players can't choose their
spawn location in random spawn mode, there's no need for the full
300-tick spawn phase.

## Please complete the following:

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

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

FloPinguin
2026-03-16 15:58:54 -07:00
FloPinguin c76ffd3641 Reduce spawn phase duration when random spawn is enabled ⏱️ (#3437)
## Description:

Reduces `numSpawnPhaseTurns` from 300 to 100 (matching singleplayer
duration) when random spawn is active. Since players can't choose their
spawn location in random spawn mode, there's no need for the full
300-tick spawn phase.

## Please complete the following:

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

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

FloPinguin
2026-03-16 15:58:26 -07:00
FloPinguin 71e5faf4ec Rebalance HvN (#3433)
## Description:

For the next v30 fix version

<img width="868" height="364" alt="imaege"
src="https://github.com/user-attachments/assets/520a999c-67e7-4c57-8651-895ad9eeb73a"
/>

HvN balancing for the revamped difficulty steps of v30 sadly doesn't
really work out...
In medium difficulty games humans nearly always win (boring)
In hard difficulty games humans usually lose
It was intended differently...

So lets get rid of medium difficulty HvN, always use hard difficulty and
disable the donation-capability for public game nations.
That will tune the human winrate towards a middle ground at about 65% I
think. Which should be nice.
Easier than in v29 (was frustrating sometimes) but not as easy as it's
now.

We can only test this in prod lol

## Please complete the following:

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

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

FloPinguin
2026-03-16 12:25:43 -07:00
FloPinguin aa59dd23be Rebalance HvN (#3433)
## Description:

For the next v30 fix version

<img width="868" height="364" alt="imaege"
src="https://github.com/user-attachments/assets/520a999c-67e7-4c57-8651-895ad9eeb73a"
/>

HvN balancing for the revamped difficulty steps of v30 sadly doesn't
really work out...
In medium difficulty games humans nearly always win (boring)
In hard difficulty games humans usually lose
It was intended differently...

So lets get rid of medium difficulty HvN, always use hard difficulty and
disable the donation-capability for public game nations.
That will tune the human winrate towards a middle ground at about 65% I
think. Which should be nice.
Easier than in v29 (was frustrating sometimes) but not as easy as it's
now.

We can only test this in prod lol

## Please complete the following:

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

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

FloPinguin
2026-03-15 21:28:40 -07:00
evanpelle 90822fc522 fix: regenerate striatofhormuz to update binary v0.30.9 2026-03-15 18:56:44 -07:00
gabigabogabu 54b3a1a7b2 Fix seam lines in Nile Delta map (#3432)
## Description:
Fix visible seam lines in the Nile Delta map caused by SVG tile
boundaries in the source image. Applied directional elevation blur (1x9
then 9x1 kernels) on land pixels only, preserving rivers and coastlines.

### Before

![before](https://raw.githubusercontent.com/openfrontio/OpenFrontIO/main/map-generator/assets/maps/niledelta/image.png)

### After

![after](https://raw.githubusercontent.com/gabigabogabu/OpenFrontIO/feature/nile-delta-seam-fix/map-generator/assets/maps/niledelta/image.png)

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

Discord: gabigabogabu

---------

Co-authored-by: FloPinguin <25036848+FloPinguin@users.noreply.github.com>
2026-03-15 15:00:12 -07:00
HulKiora b045608c89 ui: reduce HUD transparency for control, attacks, events, and hover panel (#3429)
## Description:

Reduce HUD transparency for better readability by making the Control
Panel, Attacks panel, Events/Chat panel, and Hover panel more opaque
while keeping a subtle blur effect.

## Please complete the following:

- [ x] I have added screenshots for all UI updates
- [ ] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [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:

HulKiora
Before :
<img width="518" height="134" alt="image"
src="https://github.com/user-attachments/assets/dd714a8e-5b8c-4754-b68d-a86a0f82afcf"
/>

After :
<img width="519" height="138" alt="image"
src="https://github.com/user-attachments/assets/828b88be-a071-474c-a4a2-80d1c679b3df"
/>
2026-03-15 14:59:34 -07:00
gabigabogabu 371c51f05a Fix seam lines in Nile Delta map (#3432)
## Description:
Fix visible seam lines in the Nile Delta map caused by SVG tile
boundaries in the source image. Applied directional elevation blur (1x9
then 9x1 kernels) on land pixels only, preserving rivers and coastlines.

### Before

![before](https://raw.githubusercontent.com/openfrontio/OpenFrontIO/main/map-generator/assets/maps/niledelta/image.png)

### After

![after](https://raw.githubusercontent.com/gabigabogabu/OpenFrontIO/feature/nile-delta-seam-fix/map-generator/assets/maps/niledelta/image.png)

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

Discord: gabigabogabu

---------

Co-authored-by: FloPinguin <25036848+FloPinguin@users.noreply.github.com>
2026-03-15 20:29:26 +00:00
evanpelle 3919f17e8b Revert "Rearrange homepage game boxes & tune special modifier probabilities 🎲 (#3420)"
This reverts commit ea4355f03a.
2026-03-14 19:29:57 -07:00
evanpelle c8ed6b0e70 Merge branch 'v30' 2026-03-14 19:28:38 -07:00
Aotumuri 87d1b4d473 mls (v4.17) (#3416)
## Description:

mls for v30
Version identifier within MLS: 4.16

## Please complete the following:

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

## Please put your Discord username so you can be contacted if a bug or
regression is found:
aotumuri
v0.30.8
2026-03-14 23:45:07 +00:00
evanpelle f6167d2d94 allow 3 send winner msgs, in case a client reconnects 2026-03-14 11:30:12 -07:00
Josh Harris da6969e726 Merge pull request #3426 from openfrontio/fix_stuck_lobbies
Fix public lobby timer stuck due to IPC race condition
v0.30.7
2026-03-14 06:10:13 +00:00
Josh Harris 3273931950 Fix public lobby timer stuck due to IPC race condition 2026-03-14 06:02:57 +00:00
Evan 5fb7f75f3d Server-side WebSocket message rate limiting & size enforcement (#3424)
## Description:

* Adds ClientMsgRateLimiter — a per-client token-bucket rate limiter
that gates all incoming WebSocket messages. Returns "ok", "limit"
(drop), or "kick" based on the violation type.

* Intent messages are capped at 500 bytes each (they are stored in turn
history for the game duration, so oversized intents
accumulate in server RAM). Violations kick the client.

* Winner messages bypass the byte rate limit (they include stats for all
players and can be 100s of KB) but are strictly capped at one per client
— a second winner message kicks the client.

* All other messages go through the standard per-second (10/s) and
per-minute (150/min) rate limits. Violations drop the message; byte
budget exhaustion kicks the client.

* WebSocket maxPayload set to 2 MB on game workers.
Invalid (unparseable) messages now immediately kick the client rather
than being silently dropped.
Unit tests added for all rate limiting behaviors.

## 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
v0.30.6
2026-03-13 21:15:10 -07:00
Josh Harris 4b33f3749d Fix duplicate game creation when opening private lobby (#3423)
## Description:

- Prevent `BaseModal.open()` from firing `onOpen()` twice when
Navigation.showPage() re-calls `open()` on inline modals
- Adds an `isModalOpen` early-return guard, matching existing behavior
in `OModal.open()`

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

Jish
v0.30.5
2026-03-13 19:34:59 -07:00