Commit Graph

3161 Commits

Author SHA1 Message Date
scamiv cac6ac9e1f v1 2026-02-07 23:53:29 +01:00
scamiv 8cc6c2c2aa Perf spawn train (#3130)
## Description:

Train spawning hot-path optimization (trade destination selection)

## Summary
This PR reduces per-tick overhead in train spawning by removing
temporary allocations and reducing work in the
destination-selection path.

The change focuses on `Cluster` trade destination lookup and how
`TrainStationExecution` picks a destination.

## What changed
### 1) Maintain a “trade-capable” station subset per cluster
`src/core/game/TrainStation.ts`

- `Cluster` now maintains:
  - `stations`: all stations in the cluster (unchanged)
- `tradeStations`: maintained subset of stations that can act as trade
endpoints (`City` or `Port`)
- `tradeStations` is kept in sync in:
  - `addStation()`
  - `removeStation()`
  - `clear()`

Impact:
- Trade queries no longer scan every station in the cluster; they only
scan `tradeStations`.

### 2) Add cheap eligibility helpers
`src/core/game/TrainStation.ts`

- `hasAnyTradeDestination(player)`:
- Fast early-exit check: returns as soon as it finds any eligible trade
destination.
- `randomTradeDestination(player, random)`:
- Picks a random eligible trade destination directly without
materializing an intermediate `Set`.

### 3) Use reservoir sampling for single-pass random choice
`src/core/game/TrainStation.ts`

`Cluster.randomTradeDestination()` uses reservoir sampling:
- Iterates `tradeStations` once.
- Maintains a running count of eligible stations (`eligibleSeen`).
- Replaces the selected station with probability `1/eligibleSeen`.

Properties:
- Uniform selection among eligible stations.
- One pass instead of “count then pick by index” (two pass).
- Allocation-free.
- Returns `null` when no eligible destination exists.

### 4) Update train spawning to avoid temporary sets
`src/core/execution/TrainStationExecution.ts`

- Previously: `spawnTrain()` called `cluster.availableForTrade()` and
then `random.randFromSet(...)`.
  - This built a new `Set` on the hot path.
- Now:
  - Early-exit via `cluster.hasAnyTradeDestination(owner)`.
  - Destination via `cluster.randomTradeDestination(owner, random)`.

Net effect:
- Less per-tick work and no per-spawn temporary `Set` allocations.

## Why this helps
Train spawning happens frequently and can become a hot path in large
games / large rail clusters.
Avoiding repeated allocations and reducing work inside `tick()` helps
keep frame/update time predictable.

## notes
- Trade rules are unchanged (`tradeAvailable(player)` still gates
eligibility).
- Destination selection remains random-uniform over eligible
`City`/`Port` stations that satisfy `tradeAvailable(player)`.
- `TrainStationExecution` now avoids calling `spawnTrain()` entirely
when `spawnTrains` is falsy (it was already guarded inside).




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

DISCORD_USERNAME
2026-02-05 12:16:59 -08:00
Wraith 59e808b63b fix(leaderboards): update & move reached_limit check (#3128)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #3126 

## Description:

update & move reached_limit check

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

wraith4081

---------

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-02-05 19:35:49 +00:00
scamiv b68de96c6e Perf clusters (#3127)
## Description:

This PR reduces server/client tick CPU spent on territory cluster
maintenance by:
- Cutting redundant work in `PlayerExecution.removeClusters()`
(largest-cluster bounding box reuse, fewer allocations in
`isSurrounded()` and `removeCluster()`).
- Making `calculateBoundingBox()` allocation-free per tile by switching
from `gm.cell(tile)` to `gm.x(tile)`/`gm.y(tile)` (it now only allocates
the two result `Cell`s, instead of 1 per tile).

## Commits
- `51de0a1b` core: reduce PlayerExecution cluster overhead
- `6d9d85c5` core: avoid Cell allocations in PlayerExecution
isSurrounded
- `346f6a8c` core(util): speed up calculateBoundingBox by avoiding Cell
allocations


## Notes
- This PR is intended to be behavior-preserving; changes are limited to
hot-path micro-optimizations.
- Follow-up opportunity: `calculateClusters`/flood-fill is now the top
hotspot; further wins likely come from reducing traversal work or
caching.


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

DISCORD_USERNAME
2026-02-05 10:07:17 -08:00
scamiv d40923fc18 perf(game): optimize border tile updates (#3124)
## Description

Optimize border-tile maintenance in `GameImpl` to reduce per-conquest
overhead.

Border tiles are updated whenever ownership changes; this PR trims
allocations and avoids unnecessary iteration in the hot path.

## Changes

- `src/core/game/GameImpl.ts`
- `updateBorders(tile)` no longer allocates an array of tiles; it
updates the changed tile and its 4-neighbors directly via
`forEachNeighbor`.
- `calcIsBorder(tile)` no longer calls `neighbors(tile)` / loops an
array; it checks the four cardinal neighbors via `x/y` bounds and
`ownerID`.

## Affected Functions

- `GameImpl.updateBorders(tile: TileRef)`
- `GameImpl.calcIsBorder(tile: TileRef): boolean`
- Call sites impacted by behavior/perf:
  - `GameImpl.conquer(owner, tile)`
  - `GameImpl.relinquish(tile)`

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

DISCORD_USERNAME
2026-02-04 20:19:50 -08:00
scamiv ec5fb4fa22 Pr fxlayer viewport culling (#3123)
## Description:

Reduce FX layer rendering cost by:
- Updating the offscreen FX buffer only when needed (and clearing it
once when FX ends).
- Drawing only the visible portion of the FX buffer to the main canvas
(viewport culling).
- Reusing `TransformHandler.screenBoundingRect()` as the single source
of truth for viewport bounds.
- 
## Changes
- `FxLayer`:
  - Track buffered frames and skip work when there are no active FX.
  - Use `performance.now()` for refresh timing.
- Draw only the visible map rect (clamp + small pad) instead of blitting
the full map-sized FX canvas.
- Compute the visible rect via `TransformHandler.screenBoundingRect()`.
- `GameRenderer`:
  - Thread `TransformHandler` into `FxLayer` construction.


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

DISCORD_USERNAME
2026-02-04 20:18:25 -08:00
FloPinguin c2663944e5 Stop getting gold from conquering inactive players 🔧 (#3020)
## Description:

Maybe for v29. 

In the 5M starting gold modifier games you can conquer a inactive player
(spawned but didn't do anything) and get their 5M gold.
Huge unfair advantage.
I think that even without the starting gold modifier you should not get
the gold of inactive players because its unfair.

I identify inactive players (spawned but didn't do anything) by checking
the attack stats.
I added a translation for the displayMessage "Conquered {name}, received
{gold} gold". Why was that not translated?
I added a new message "Conquered {name} (Inactive player, received no
gold)".

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

---------

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-02-04 22:12:30 +00:00
Ryan 41a9bb80c0 Added source for join context (#3116)
## Description:

Added source for join context

## 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-02-04 10:01:05 -08:00
FloPinguin a8836f76d3 Reduce bot farming problem (#2895)
## Description:

Explanation of the bot farming strategy in the discord:
https://discord.com/channels/1359946986937258015/1359949371956789289/1460928540575928478
"the result is that a player can build unlimited factories for 125 000
gold discount, trade with themselves with each train being worth 50 000
gold. First the 25 000 for neutral trade and then another 25 000 when
the bot is harvested."
"If you have a minute and ally people around you it should be trivial to
get 10 of both cities and factories for 1.25mil"

It's debatable if we want to let people do that (close this PR) or see
it as an abusive mechanic.

Here is the fix, bots try to delete all structures now. You can simply
retake them to stop the deletion:


https://github.com/user-attachments/assets/ac1ca846-50bd-42fa-8e25-5ac25a6d627e

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

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-02-04 11:39:35 +00:00
FloPinguin 904425cab0 Prevent players from nuking their teammates structures 💥 (#3105)
## Description:

It is possible to hit your teammates while throwing a nuke onto water or
enemies.
This PR blocks the nuking entirely if you would hit a teammates
structure. Because they are valuable.
Feature requested by Wonder :)


https://github.com/user-attachments/assets/448a3444-cc3d-4e76-acaf-595decab1634

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

---------

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-02-04 11:38:49 +00:00
evanpelle 9a4742f378 update package-lock.json 2026-02-03 20:30:27 -08:00
Evan 294a1b4784 move lobby websockets to worker (#2974)
## Description:

Currently only the master process sends public lobby updates to clients.
This is not scalable since it could overload the master process.

In this PR, the master uses IPC to send public lobby info to all
workers. Then clients connect to a random worker to get public lobby
updates via websocket. This way clients never connect directly to the
master websocket.

The flow looks like this:

Every 100ms:
1. Master schedules a public game on a random worker if new games are
needed
2. Master broadcasts public lobby info to all workers (all public games
& num clients connected to each game)
3. Each worker responds to that update with the number of clients
connected to its own public games
4. Master then updates its public lobby state so it knows how many
clients are connected to each public game

## 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-02-03 18:26:38 -08:00
Ryan 9294b73a88 add import, somehow missing?? (#3113)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #(issue number)

## Description:

add import, somehow missing??

## 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-02-03 16:09:06 -08:00
FloPinguin 596bc90134 Fix the new mobile styles a bit 🖌️ (#3106)
## Description:

### 1. PlayerInfoOverlay had less margin top than the leaderboard and
the game controls. Fixed.

### 2. PlayerInfoOverlay  did overlap with HeadsUpMessage. Fixed.

Previous:

<img width="543" height="174" alt="Screenshot 2026-02-03 184835"
src="https://github.com/user-attachments/assets/8687294b-feb6-409d-995a-971986a9d406"
/>

Now:

<img width="510" height="299" alt="Screenshot 2026-02-03 185117"
src="https://github.com/user-attachments/assets/8b81f5ed-98ea-4154-b485-9de4ed974939"
/>

### 3. Fixed border radius of the lower panels

Previous:

<img width="1200" height="162" alt="Screenshot 2026-02-03 184938"
src="https://github.com/user-attachments/assets/72dc77c4-8992-4812-8b5d-e100e16fe91e"
/>

<img width="1081" height="122" alt="Screenshot 2026-02-03 185014"
src="https://github.com/user-attachments/assets/0291e305-faed-41d2-b5a9-db795b61a8d2"
/>

Now:

<img width="1237" height="151" alt="Screenshot 2026-02-03 184953"
src="https://github.com/user-attachments/assets/40565ab4-cdad-4ea6-81e5-f24d485c7199"
/>

<img width="1054" height="99" alt="Screenshot 2026-02-03 185004"
src="https://github.com/user-attachments/assets/ce091c16-74ac-4a05-8843-8493e08ba6c3"
/>

### 4. Give PlayerInfoOverlay the same gap between gold icon and gold
text as in ControlPanel

Previous:

<img width="772" height="759" alt="Screenshot 2026-02-03 191150"
src="https://github.com/user-attachments/assets/49b14025-9d28-447d-9370-64ad30532abd"
/>

Now:

<img width="803" height="748" alt="Screenshot 2026-02-03 191203"
src="https://github.com/user-attachments/assets/b4749557-bf10-4643-83b1-5e9d22f122ed"
/>

## 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-02-03 15:16:17 -08:00
Ryan c9d8ed767c Add getClientIDForGame for consistent client IDs per game session (#3108)
## Description:

- Add getClientIDForGame function to Auth.ts that generates and stores a
consistent clientID per gameID using sessionStorage
- Update HostLobbyModal to use getClientIDForGame for lobby creation
- Update Matchmaking to use getClientIDForGame when joining games
- Update PublicLobby to use getClientIDForGame when joining lobbies


This enables reconnection support by ensuring the same clientID is used
when rejoining a game session.

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

---------

Co-authored-by: Evan <evanpelle@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 15:07:12 -08:00
Aotumuri 144442a99b fix: prevent button content from overflowing in translated labels (#3112)
## Description:

Prevents translated button text from overflowing its container by
constraining layout and clipping excess content.

before
<img width="234" height="133" alt="スクリーンショット 2026-02-04 6 46 35"
src="https://github.com/user-attachments/assets/2cfe4f3e-ac5c-42d0-8175-76ca53fa3b1b"
/>
after
<img width="189" height="135" alt="スクリーンショット 2026-02-04 6 46 46"
src="https://github.com/user-attachments/assets/e2fd2439-6cd3-4831-86b2-28a374bc7ba4"
/>

## 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-02-03 15:02:07 -08:00
Ryan fce157314f fix: validate base username length separately from clan tag (#3098)
## Description:

fix: validate base username length separately from clan tag)
## 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-02-03 13:42:12 +00:00
Aotumuri f5cba9a495 fix: remove incorrect host display in JoinLobbyModal (Public game) (#3099)
## Description:
Hide the host badge when joining public lobbies

before
<img width="802" height="635" alt="スクリーンショット 2026-02-03 21 45 45"
src="https://github.com/user-attachments/assets/2b8bd5a0-3023-4bd3-9042-1bbd0649e499"
/>

after
<img width="668" height="702" alt="スクリーンショット 2026-02-03 21 44 00"
src="https://github.com/user-attachments/assets/65eb9b66-99b0-46ce-a786-55974a443010"
/>


## 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-02-03 13:26:47 +00:00
Aotumuri 3429c9d8e9 fix: show full flag names in selector (#3103)
## Description:

Flag selector country names no longer truncate with ellipses; they wrap
normally for readability.

before
<img width="561" height="182" alt="スクリーンショット 2026-02-03 22 21 01"
src="https://github.com/user-attachments/assets/965ab93e-e10f-42a0-8771-84f042c31e22"
/>
after
<img width="582" height="217" alt="スクリーンショット 2026-02-03 22 21 11"
src="https://github.com/user-attachments/assets/9c6aa840-5af7-46a7-9f54-58d78e021304"
/>

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

Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-02-03 13:24:50 +00:00
Aotumuri 8851a110a3 fix: align leaderboard modal background with other modals (#3100)
## Description:
Aligned the LeaderboardModal background styling with other modals (e.g.,
HelpModal). Uses the same inline background/blur/border treatment to
improve visual consistency.

before
leaderboard
<img width="848" height="657" alt="スクリーンショット 2026-02-03 22 07 58"
src="https://github.com/user-attachments/assets/b31c0754-00e0-4248-9e2d-97869df99acb"
/>
other
<img width="921" height="686" alt="スクリーンショット 2026-02-03 22 08 07"
src="https://github.com/user-attachments/assets/e84ab4e0-64b1-490f-8d93-d745f4eabbbb"
/>

after 
leaderboard
<img width="852" height="650" alt="スクリーンショット 2026-02-03 22 08 20"
src="https://github.com/user-attachments/assets/6f4a4073-4d6e-4ca8-8ef1-fb08240a5e6b"
/>
other
<img width="857" height="685" alt="スクリーンショット 2026-02-03 22 08 35"
src="https://github.com/user-attachments/assets/367607f7-f665-4e1e-9c34-4566d2b68570"
/>

## 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-02-03 13:22:27 +00:00
FloPinguin 172945bbfc Missing translation: "host_modal.crowded" (#3102)
## Description:

Join Lobby Modal will show:
Crowded modifier
Enabled

## 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-02-03 13:21:17 +00:00
Ryan 2baaebfef3 JoinLobbyModal for public and private lobbies (#3097)
## Description:

Replaced the src/client/JoinPrivateLobbyModal.ts with a new
src/client/JoinLobbyModal.ts which handles both public + private
lobbies.

<img width="771" height="714" alt="image"
src="https://github.com/user-attachments/assets/7ac55d91-3f0c-4f99-b960-cea9e617538d"
/>

also made a "connecting" to the lobby 
<img width="772" height="708" alt="image"
src="https://github.com/user-attachments/assets/a2812462-c5f4-459a-b63a-49d93bb2a6a2"
/>


It also needed to be updated to address the issue with the modal using
both polling + websockets

## 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-02-02 21:02:20 -08:00
Evan d04f90ec4a mobile control panel (#3096)
Relates to #2260

## Description:

Redo the control panel to be more mobile friendly and take up less space

![Uploading Screenshot 2026-02-02 at 8.09.13 PM.png…]()
<img width="584" height="236" alt="Screenshot 2026-02-02 at 8 09 34 PM"
src="https://github.com/user-attachments/assets/d48906d5-3653-499c-9b08-b661d5e7d4a4"
/>

Describe the 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:

evan
2026-02-02 20:12:43 -08:00
Evan 7d3ec0fcb8 Move player info panel to top of the screen & simplify (#3087)
related to #2260

## Description:

* Moves the player info panel from the right to the top of the screen
* Disable the header ad for now because it would cover up the player
info, we'll find a better place for it in the future
* Remove the collapsable button/functionality. It's hard to even click
the button because the panel disappears when you move away from a
player, and I think the info is too valuable to ever need to be
collapsed.
* Removed the "land" and "irradiated land" since it didn't add much
value
* Remove all alt text & translation, you can't hover over the player
overlay so it's irrelevant.
* put troop info inside the troop bar to reduce amount of text


<img width="479" height="88" alt="Screenshot 2026-02-01 at 8 57 33 PM"
src="https://github.com/user-attachments/assets/3b72eb16-2efa-4c00-a4d0-5e085548fa78"
/>

<img width="438" height="136" alt="Screenshot 2026-02-01 at 8 58 06 PM"
src="https://github.com/user-attachments/assets/285bb2c9-6deb-4ee8-bcc8-743cccd6b77e"
/>

## 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-02-02 09:09:52 -08:00
Mattia Migliorini 6b80337aa9 Allow accepting alliance via radial menu during alliance request cooldown (#3092)
## Description:

Currently, when you send an alliance request to another player and it
gets rejected, but the same player sends you an alliance request back
during your alliance request cooldown, you cannot accept it via the
radial menu, you need to do that via the notification on the bottom
right.

This is not consistent with when you receive an alliance request outside
of the cooldown.

This PR checks for incoming alliance request for the same player before
checking the outgoing request cooldown, therefore allowing you to accept
incoming alliance requests via the radial menu button even during
cooldown.

## 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-02-02 08:30:23 -08:00
FloPinguin 996472edc9 Improve SinglePlayerModal a bit 🖌️ (#3083)
## Description:

- Add warning for custom games (you won't get achievements)
- Remove medal display for maps without nations (Baikal nuke wars)

<img width="813" height="572" alt="image"
src="https://github.com/user-attachments/assets/fb80a160-a175-4a24-8706-ddaa07d0bde5"
/>

<img width="720" height="555" alt="Screenshot 2026-02-01 162436"
src="https://github.com/user-attachments/assets/d4c28d71-364c-4255-8ecc-31703a5659bf"
/>


## 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-02-01 20:13:43 -08:00
FloPinguin 8ab9cef65b Various little nation improvements 🤖 (#3082)
## Description:

- Maybe greet nearby players with a 👋 emoji in the earlygame (make
nations feel a little bit more lively)
- Destroying a transport ship / capturing a trade ship of a nation now
updates the relation (mainly on higher difficulties)
- On hard difficulty: Only lift embargos if we have a friendly relation.
On impossible difficulty: Don't lift embargos
- Improve totalPlayers calculation and return value of
`hasTooManyAlliances` in `NationAllianceBehavior`

## 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-02-01 20:12:19 -08:00
Ryan e4280c28e1 Add Ranked 1v1 Leaderboard (#3008)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #(issue number)

## Description:

@wraith4081 's pr

updates the stats modal to show both 1v1 and clan stats

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

---------

Co-authored-by: Wraith <54374743+wraith4081@users.noreply.github.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
2026-02-01 14:58:54 -08:00
FloPinguin 6407dc418a Adblockers blocked OUR OWN source files 🔧 (#3085)
## Description:

Renamed ad files because adblockers blocked them because of their name. 
When ES modules fail to import, the entire application breaks.

## 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-02-01 16:57:33 +00:00
evanpelle 986d509a1c Merge branch 'v29' 2026-01-31 14:43:00 -08:00
FloPinguin 2e609fd858 Move betrayal button, remove betrayal confirmation 🔧 (#3076)
## Description:

- Move betrayal button to the boat-sending-button-location (you can't
send boats to allies) to prevent missclicks
- Remove betrayal confirmation

<img width="260" height="248" alt="image"
src="https://github.com/user-attachments/assets/0a25fc9c-c8a0-4ba9-a8c8-971d6a7a0511"
/>

## 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-01-31 13:53:24 -08:00
FloPinguin 0286224299 Move betrayal button, remove betrayal confirmation 🔧 (#3076)
## Description:

- Move betrayal button to the boat-sending-button-location (you can't
send boats to allies) to prevent missclicks
- Remove betrayal confirmation

<img width="260" height="248" alt="image"
src="https://github.com/user-attachments/assets/0a25fc9c-c8a0-4ba9-a8c8-971d6a7a0511"
/>

## 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-01-31 13:52:58 -08:00
Evan 5452ede38a Ad video ad during spawn (#3078)
## Description:

Ads a small video on the bottom left of the screen during 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:

evan
2026-01-31 12:45:20 -08:00
Evan 3388fd728c Create Video ad lit component (#3074)
## Description:

Creates an embedded Playwire video ad with status callbacks

## 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-01-31 12:25:34 -08:00
evanpelle 19d0376532 better error & logging when client sends invalid intent, don't close the connection eithehr 2026-01-31 09:17:53 -08:00
DenelDuck b6b74befa0 add colored borders to player's quickchat option buttons (#2821)
Resolves #2820

## Description:

Add colored borders to the `chat-option-button` corresponding to each
players territory color.

<img width="630" height="565" alt="Image"
src="https://github.com/user-attachments/assets/91a99230-0581-4d83-a470-9a02ba43c045"
/>

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

denelduck

---------

Co-authored-by: VariableVince <24507472+VariableVince@users.noreply.github.com>
2026-01-30 19:58:34 -08:00
Evan 6c2e0d1528 Fix matchmaking double join bug (#3065)
## Description:

There were several issues with the matchmaking modal:

1. It was defined twice (once before login, and once after login), so
players would sometimes join the matchmaking queue twice.
2. When clicking away from the modal (not clicking the back button), the
"onClose" callback was not triggered. So if a person closed & reopened
the modal, they would join twice'
3. Cache the userMe response so it can be called multiple times

## 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.29.11
2026-01-30 15:27:34 -08:00
Evan 02dc5fc153 Add glowing red dot on store when skins change (#3066)
## Description:

Hash the pattern + is for sale and store it in local storage. then check
if the new cosmetics hash is different from the one we last saw. If it's
different, add a glowing red dot on the store. After user clicks it,
then update the hash and remove the dot.
<img width="1030" height="143" alt="Screenshot 2026-01-29 at 3 54 46 PM"
src="https://github.com/user-attachments/assets/e5727764-40e4-45e1-b651-65816e657067"
/>

## 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-01-30 14:24:55 -08:00
FloPinguin 683ba4c6c1 Make easy difficulty easier 📊 (#3072)
## Description:


https://www.reddit.com/r/Openfront/comments/1qquvdg/difficulty_scaling_in_single_player/
People seem to feel that easy is not easy enough, even after the various
nerfs in multiple places.
So let's touch DefaultConfig.

## 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-01-30 13:45:19 -08:00
FloPinguin 19cdc3fe5f Make easy difficulty easier 📊 (#3072)
## Description:


https://www.reddit.com/r/Openfront/comments/1qquvdg/difficulty_scaling_in_single_player/
People seem to feel that easy is not easy enough, even after the various
nerfs in multiple places.
So let's touch DefaultConfig.

## 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-01-30 13:45:00 -08:00
Sardi 13117251af Add new map “The Box” (#3054)
<img width="1670" height="200" alt="banner"
src="https://github.com/user-attachments/assets/b6561231-71dc-46dd-a521-453d4e97931f"
/>

## Description:

This proposal adds a new, completely flat map called "The Box," where
players will find themselves on a completely flat landmass and will only
be able to trade by land using trains and factories.

- Map size: 2048×2048 pixels
- Binaries generated with MapGenerator (map.bin, map4x.bin, map16x.bin)
- Integrated into arcade category and multiplayer playlist
- English and Spanish translations added
- 13 nations/bots with unique and thematic names:
 
> - **Middle Defender (located in the center)**
> - **King of the Corner (located in the top-left corner)**
> - Suspicious Ally
> - Punch Merchant
> - Nuke Thrower
> - Fullsender
> - Factory Builder
> - Front Manager
> - Box Fighter
> - Cage Liberator
> - Train Trader
> - Non-peaceful Bot
> - **Evan The Dev** (special mention)

All other bots are distributed to cover the map evenly.

<img width="838" height="835" alt="Screenshot 2026-01-28 at 17 39 45"
src="https://github.com/user-attachments/assets/4665088d-cb94-4db3-8602-8a22b63bfee2"
/>

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

sardidefcon
2026-01-29 19:49:10 -08:00
evanpelle bec5b5f976 Merge branch 'v29' 2026-01-28 19:47:23 -08:00
Evan 1eed561be5 Add enzo video tutorial in the help modal (#3059)
## Description:

Add video at top of help section, also show a glowing dot for new
players.

<img width="301" height="133" alt="Screenshot 2026-01-28 at 7 25 23 PM"
src="https://github.com/user-attachments/assets/c6b01853-f066-470f-a22d-8995fd81fe0f"
/>

## 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.29.10
2026-01-28 19:43:25 -08:00
Ryan 80c8ddda0f Shop new tag (#3057)
adds a "tag" of NEW to the shop which pulses
<img width="159" height="83" alt="image"
src="https://github.com/user-attachments/assets/603adbaa-0699-443b-b7de-2fe383cdf759"
/>

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

w.o.n
v0.29.9
2026-01-28 16:09:11 -08:00
evanpelle c54c73d157 Merge branch 'v29' 2026-01-28 16:06:32 -08:00
Ryan 6d3d273889 Shop new tag (#3057)
## Description:

adds a "tag" of NEW to the shop which pulses
<img width="159" height="83" alt="image"
src="https://github.com/user-attachments/assets/603adbaa-0699-443b-b7de-2fe383cdf759"
/>


## 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-01-28 15:56:53 -08:00
evanpelle 936b689769 bugfix: duplicate matchmaking modals causing elo to display unknown v0.29.8 2026-01-28 13:06:43 -08:00
FloPinguin f20028a2a1 Show troop count of troop transport boats (#3056)
## Description:

Troop count display for naval invasion message:

<img width="398" height="131" alt="Screenshot 2026-01-28 204213"
src="https://github.com/user-attachments/assets/d7ccf2a8-9974-4f12-9901-e603426a8e56"
/>

On hover, PlayerInfoOverlay shows the troop count now:

<img width="504" height="99" alt="Screenshot 2026-01-28 202916"
src="https://github.com/user-attachments/assets/46f7685f-8c0e-4156-8d02-8a68dbcffde0"
/>


## 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-01-28 12:39:30 -08:00
evanpelle dec926c54c bugfix: usernames are reset after each game v0.29.7 2026-01-28 12:13:59 -08:00
FloPinguin a0ec1dd646 For v29.6: More team games 🧑‍🤝‍🧑 (#3051)
## Description:

Use ffa:teams ratio of 3:2

## 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
v0.29.6
2026-01-28 11:30:26 -08:00