Commit Graph

2526 Commits

Author SHA1 Message Date
evanpelle 793efe4dd1 Revert "Special bot names (#2552)"
This reverts commit 8f32746bb2.
2026-01-01 16:32:57 -08:00
evanpelle e4a6e3bd20 Revert "Special bot names 2 (#2609)"
This reverts commit 099337d83e.
2026-01-01 16:30:41 -08:00
evanpelle e319de99ec Revert "Add Christmas emojis (#2634)"
This reverts commit 507f391aa1.
2026-01-01 16:14:33 -08:00
evanpelle 9370496c7f Revert "Christmas Themed Homepage 2 (#2628)"
This reverts commit 6d58abfdbb.
2026-01-01 16:14:20 -08:00
evanpelle f5f89e4aa7 Merge branch 'v28' 2026-01-01 14:25:45 -08:00
evanpelle 435f2c4fa1 Revert "Christmas Themed Homepage (#2608)"
This reverts commit f256f497ce.
2026-01-01 14:04:13 -08:00
FloPinguin ad7c30e44c Fix nation warship edge-case issue ⛴️ (#2760)
## Description:

On the world map, if two teams of nations are fighting each other (left
side vs. right side), there is a possibility that an extreme warship
battle involving nearly 200 warships could occur. This PR helps resolve
that edge-case issue a bit.

<img width="623" height="647" alt="Screenshot 2025-12-31 155924"
src="https://github.com/user-attachments/assets/993c0b08-eccc-491f-aae9-7ea4fd8943f3"
/>

## 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-01 13:31:54 -08:00
FloPinguin fb6bbf1730 Reduce nation cheating even more 📊 (#2757)
## Description:

WIth my other new PR "Nations send much better nukes now (Part 1)"
nations got smarter.

Because of that, and based on player feedback, my own tests and youtube
videos (pros like enzo can't beat impossible difficulty nations without
warship infestations) we need to turn down the cheating.

With this PR, I reduced the cheating by 50% (again).

## 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-01 13:30:30 -08:00
FloPinguin 23e4bf6725 ☢️ Nations send much better nukes now (Part 1) ☢️ (#2756)
This is a very important PR for HumansVsNations (But also for
singleplayer).
Humans will throw lots of nukes onto nations, but nations didn't do
that. Until now :)

## Refactor

- Moved all the nuking logic to the new file `NationNukeBehavior.ts`
- Moved `randTerritoryTileArray()` and `randTerritoryTile()` to the new
file `NationUtils.ts` because we need that method in multiple places now
- Because we already have an `NationUtils.ts` (It contains the method
`createNationsForGame` for HumansVsNations) I renamed the old one to
`NationCreation.ts` to avoid confusion

## Bug fixed

- `allRelationsSorted()` in `PlayerImpl` returned dead players all the
time... Which caused nations to not attack / send nukes in some cases...

## Nuke-sending features / improvements

- On hard and impossible difficulty, nations no longer make sure that
nukes will only hit inside of their targets border. This logic very
often stopped nations from throwing nukes. Now their nukes are allowed
to hit TerraNullius (=> ocean!). And in team games, it's even allowed
that their nukes hit other non-friendly players as well! This is very
important for HumansVsNations.
- The basic check for SAMs now gets skipped if we are on easy difficulty
(easy nations are not smart enough to do that)
- I improved the basic check for SAMs (medium difficulty) a bit (nations
send less nukes into SAMs)
- On hard and impossible difficulty, we now use the new method
`isTrajectoryInterceptableBySam()` to avoid SAMs completely. It's
mirroring `NukeTrajectoryPreviewLayer.ts` logic a bit.
- I added "perceived cost" to simulate nations saving up for a MIRV
(Otherwise most hard/impossible nations will spend all their gold on
nukes). But if we are in a team game (MIRVs are not relevant) or if we
already saved up for a MIRV, the "perceived cost" gets ignored.
- Updated the "most hated player" selection in `findBestNukeTarget()` to
ignore very weak players. We don't need to throw nukes at players which
we can easily steamroll by land.
- Added `findFFACrownTarget()` to nuke the crown (based on difficulty).
- Added `findStrongestTeamTarget()` to nuke the strongest team.
- Updated `randTerritoryTile()` so that it has a higher chance of
returning the tiles of a
"leftover-nuked-to-death-player-with-some-tiles-left": `if
(p.numTilesOwned() <= 100) {return
random.randElement(Array.from(p.tiles()));}`.
- Changed `const range = nukeType === UnitType.HydrogenBomb ? 60 : 15`
to `config().nukeMagnitudes(nukeType).inner`. Should make more sense.
- Adjusted `nukeTileScore()` to search for units in
`this.mg.config().nukeMagnitudes(nukeType).inner` instead of fixed 25
- Adjusted `nukeTileScore()` to account for unit levels (levels got
ignored previously). Also increased score for ports from 10_000 to
15_000.
- I made sure that nations can nuke EVERY SINGLE TILE from an enemy,
even if the enemy has no structures ("Prefer tiles that are closer to a
silo" can no longer make the `nukeTileScore()` drop too much,
`bestValue` in `maybeSendNuke()` starts at -1 now)
- In the entire nuking logic, factories were missing. Now they are
added.

## Media

Nation team vs. nation team: They are nuking the very last pixels of
red, just like humans would do it 😀

<img width="915" height="683" alt="image"
src="https://github.com/user-attachments/assets/109c7921-b959-4aa9-a971-0d7742971686"
/>

Hard difficulty FFA game: Nations throwing much more nukes. And they are
nuking the crown.


https://github.com/user-attachments/assets/a6e43924-a6ca-4b1a-a578-4e4f8252e383

Lots of nukes flying:


https://github.com/user-attachments/assets/8fc4edad-a6e6-4476-8a86-08cdef58169e

## 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: iamlewis <lewismmmm@gmail.com>
2026-01-01 13:29:46 -08:00
Vahant Sharma 96622779d1 Add tooltips to Win/Loss Score columns in clan stats (#2752)
Resolves #2508

## Description:

Adds hover tooltips to the "Win Score" and "Loss Score" column headers
in the clan stats table to help players understand what these weighted
scores represent.

### Changes Made
- Added tooltip to **Win Score** column: "Weighted wins based on clan
participation and match difficulty"
- Added tooltip to **Loss Score** column: "Weighted losses based on clan
participation and match difficulty"
- Uses native HTML `title` attribute (follows existing codebase
patterns)
- Fully i18n-ready via `translateText()` - other languages will be
translated via Crowdin

### Implementation Details
- **Files Modified**: 2 files, 4 lines total
  - `resources/lang/en.json`: Added 2 tooltip translation keys
- `src/client/StatsModal.ts`: Added `title` attributes to table headers
- No breaking changes

### Expected Behavior
When hovering over "Win Score" or "Loss Score" column headers, users see
a tooltip explaining the weighted scoring system based on clan
participation and match difficulty.

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

![correctimplementation](https://github.com/user-attachments/assets/bbbad9ab-36cf-4364-96ff-feff6ee966cd)
2026-01-01 10:26:34 -08:00
Ryan 3dcd38a58d lobby websocket instead of polling (#2727)
## Description:
Changes game lobbies into websockets instead of polling

## 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: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
2026-01-01 09:38:33 -08:00
bijx 9d5f167446 Feat: Strait of Hormuz map (#2747)
## Description:
Introduces the Strait of Hormuz section in the Persian Gulf as a map!
This map is actually crazy fun to play on because of how the water
narrows to a small strait where control is necessary otherwise enemies
can transport boat to you easily. I figured a strategic map based on
modern-ish day conflicts would fit the theme, but man it's a great map
to play on.

### Full Map
<img width="2739" height="1822" alt="image"
src="https://github.com/user-attachments/assets/f35bdefa-723a-4bb2-9dc9-fb42898528ce"
/>

### In game with nations
<img width="2218" height="1502" alt="image"
src="https://github.com/user-attachments/assets/00e350cf-8654-4638-8654-178accdf6a48"
/>



## 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
2025-12-31 15:55:43 -08:00
bijx 59b9cf521a Fix: Skewed SVGs in Radial Menu (#2749)
## Description:

I believe this bug came after the introduction of the new donation
button in the radial menu (#2708) causing the rectangular SVGs to get
squished/skewed into square aspect ratios. This fix adds a little check
to fallback onto original image dimensions when an SVG's aspect ratio
isn't available. I tried a hardcoded fix earlier but if we ever decide
to add different scaled icons into the radial menu again, this will
automatically ensure the correct aspect ratio is used and the icon is
centered properly.

### Before Fix
<img width="1133" height="473" alt="image"
src="https://github.com/user-attachments/assets/5f06b19c-7072-4650-a1b7-4cb2bf1200dc"
/>

### After Fix
<img width="840" height="421" alt="image"
src="https://github.com/user-attachments/assets/176f1e7b-84bf-4b06-9ad6-4031e516d4ff"
/>

## 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
2025-12-30 20:45:43 -08:00
evanpelle b5a0541202 Revert "Fix Ctrl+Click for Macs, and alphabetize gitignore (#2720)"
This reverts commit 40eea22007.

Commit breaks map dragging ability.
2025-12-30 16:50:57 -08:00
Bruce Clounie 40eea22007 Fix Ctrl+Click for Macs, and alphabetize gitignore (#2720)
Resolves #2719 
- [X] Ran `npm run format`
- [X] Ran `npm run lint:fix`
- [X] Ran `npm test`
- [X] Manually tested fixes

## Description:

### What problem(s) was I solving?

On Mac, `Ctrl+Click` is commonly used as a substitute for right-click to
open context menus. However, in OpenFront, `Ctrl+Click` was triggering
both the context menu, AND causing an attack.

This effectively prevented Mac users from being able to ally with
bots/nations, as trying to ally would cause you to attack them.

### What changes did I make?
- `Ctrl+Click` on Mac no longer triggers an attack, allowing players to
properly interact with the alliance system

### How I implemented it

1. Added an `isMac()` method to `InputHandler` which encapsulates the
"is mac" logic, and lets it be mocked during tests
2. In the `onPointerUp` handler, added a check: if on Mac and
`ControlLeft` is held, emit a `ContextMenuEvent`, and then return
(instead of continuing to also create a `MouseUpEvent`)
3. Extracted magic numbers for mouse button checks into descriptive
helper methods (`isMiddleMouseButton`, `isNonLeftMouseButton`) for
improved code clarity
4. Added clarifying comments throughout the pointer event handlers

Last, alphabetized the `.gitignore` file and organized it into "Folders"
and "Files" sections to make it easier to read.

### How to verify it

#### Manual Testing
- [X] On a Mac, hold `Ctrl` and left-click on another nation - verify
the context menu opens (not an attack)
- [X] On a Mac, right-click should still open the context menu as
expected
- [X] On Windows/Linux, `Ctrl+Click` continue to work as before
(modifier key for build menu if configured)
- [X] Regular left-click still triggers attacks/interactions as expected

#### Automated Testing
- [x] New unit test added: `Mac Ctrl+Click Context Menu` - verifies that
`Ctrl+Click` on Mac emits `ContextMenuEvent` instead of `MouseUpEvent`

### Description for the changelog

Fixed `Ctrl+Click` on Mac to properly open the context menu instead of
triggering an attack, restoring the ability for Mac users to form
alliances with other nations.

## 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:
Terekhov
2025-12-31 00:26:00 +00:00
DevelopingTom ec694593a6 New Year's Eve FX (#2745)
## Description:

Happy new year! 

- Atom and hydro:


![test_firework](https://github.com/user-attachments/assets/892004fe-372d-4718-9b44-a311049dab20)

- Mirv:


![firework_mirv](https://github.com/user-attachments/assets/10ee4b64-7123-47e2-92d5-7d8fb6cbc992)

## Please complete the following:

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

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

IngloriousTom
2025-12-30 16:10:00 -08:00
DevelopingTom 33deb66ba6 Remove christmas FX (#2744)
## Description:

Santa will be back.

Reverted all FX to the regular theme.

## Please complete the following:

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

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

IngloriousTom
2025-12-30 13:57:35 -08:00
Wraith 8f6d3a236a fix(client): validate lobby IDs and sanitize logs (#2741)
## Description:

validate lobby IDs and sanitize logs

## 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>
2025-12-30 20:11:39 +00:00
Duwibi 11b2591fa6 Add Two Lakes (#2743)
## Description:
This PR adds the Two Lakes map, based on the irl area around lake Ohrid
and lake Prespa

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:

DISCORD_USERNAME
Nikola123
2025-12-30 19:34:51 +00:00
Abdallah Bahrawi 09a1cf885f Add red warning circle when nuke would break alliance (#2728)
## Description:

When placing a nuke (Atom Bomb or Hydrogen Bomb), the range circle now
turns red to warn players when the attack would break an alliance.

<img width="456" height="333" alt="Screenshot 2025-12-28 211927"
src="https://github.com/user-attachments/assets/dfe6f874-3f8b-4662-8877-0af30aa20139"
/>


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

abodcraft1

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
2025-12-30 17:55:15 +00:00
Evan 4f3d9df46a vite: fix docker build (#2738)
## Description:

The sync-assets wasn't executing on docker-build. so instead just import
it from resources/ directory, vite logs a warning but I think that's
okay for now.

## Please complete the following:

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

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

evan
2025-12-29 18:37:51 -08:00
FloPinguin d321c08d92 Nations now gang up on players and prioritize traitors/AFK players 🤖 (+ other improvements) (#2730)
## Description:

- **Nations now specifically target AFK players, traitors, and players
who are already being attacked (they gang up on them).** Depends on the
difficulty.
- Added ally assistance directly to the attack order (instead of calling
it separately beforehand).
- Added ally assistance to `findBestNukeTarget`.
- Removed some checks from `findBestNukeTarget` (not necessary; better
checks will follow in a dedicated nuking PR).
- Relation updates on attack now depend on difficulty (makes Easy &
Medium nations a bit easier).
- On betrayal, every nation in the game previously received a –40
relation penalty toward the betrayer. That was too extreme, so now this
only applies only to neighbors.
- Nations send fewer alliance requests now; it felt like too many
before.
- In team games, nations may now reject alliance requests more often
(depending on difficulty).
- To ensure there are enough non-friendly players to stop the crown with
nukes, nations may now reject alliance requests if the other player has
too many alliances (on Hard and Impossible difficulty).
- Rebalanced nation emoji usage a bit.
- Nations may now send an emoji when they get MIRVed.

## 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: iamlewis <lewismmmm@gmail.com>
2025-12-29 10:16:26 -08:00
Ryan f1561df470 Bomb Direction (#2435)
Resolves #2434 

## Description:

Allows bomb direction to be inverted by pressing a hotkey - currently
"U".

**Check the issue for screenshots / videos.**

## 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: iamlewis <lewismmmm@gmail.com>
2025-12-29 09:03:46 -08:00
Wraith 26f5d40819 build: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage (#2703)
- Replace Webpack with Vite for faster client bundling and HMR.
- Migrate tests from Jest to Vitest and update configuration.
- Update Web Worker instantiation to standard ESM syntax.
- Implement Env utility in `src/core` for safe, hybrid environment
variable access (Vite vs Node).
- Refactor configuration loaders to remove direct `process.env`
dependencies in shared code.
- Update TypeScript environment definitions and project scripts for the
new toolchain.
- Remove the [depracated usage of the
husky](https://github.com/typicode/husky/releases/tag/v9.0.1).

## Description:

migrate build system to Vite and test runner to Vitest & Remove
depracated husky usage

## 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
- [ ] 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: evanpelle <evanpelle@gmail.com>
2025-12-28 22:10:26 -08:00
FloPinguin f6412a5979 Re-Enable HumansVsNations 🎉 (#2689)
## Description:

**HumansVsNations is back!**

The original PR had an issue: only the nations listed in the map’s
`manifest.json` were being spawned, which resulted in completely
unbalanced games.

What did I change with this PR?

- The number of humans and nations is now always the same.
- If a map contains too many nations, we take a random subset.
- If a map doesn’t contain enough nations, we dynamically add additional
ones. These get random spawn locations, and their names are taken from
the new name generator `NationNames.ts`. The name generator was taken
from the closed PR #2245 (idea from @VariableVince).

These changes apply to private lobbies and singleplayer as well. In
singleplayer, you now simply play a 1-vs-1 against a nation.

For public lobbies, we use 50% of the regular team-game player count.
The remaining 50% are nations.

We are also using the Hard difficulty for HumansVsNations.
At the moment, it’s important that nations cheat a little because humans
can donate troops, whereas nations cannot, at least not yet. In the
future, we may make that work.

We might need to adjust the difficulty or do fine-tuning depending on
the humans’ win rate in production. Ideally, we want a ~50% win rate;
otherwise, the mode may become boring. Over time, humans will likely
develop strategies that nations can’t counter, in which case we’ll need
to improve the nation AI.

Here is a screenshot showing that the number of nations now matches the
number of humans in the private lobby UI:

<img width="806" height="304" alt="Screenshot 2025-12-25 004023"
src="https://github.com/user-attachments/assets/cb4ac6f6-13cc-452c-8cc5-7a500670d7f2"
/>

The `PuplicLobby` display was a bit bugged for HumansVsNations:

<img width="532" height="191" alt="Screenshot 2025-12-23 221832"
src="https://github.com/user-attachments/assets/3950bcd9-0072-4c28-b1a0-83c0a24e9b8e"
/>

So I fixed it to look like this;

<img width="532" height="195" alt="Screenshot 2025-12-23 224127"
src="https://github.com/user-attachments/assets/690fc554-b607-4c8a-8b22-0c2912ee671a"
/>

## 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: iamlewis <lewismmmm@gmail.com>
2025-12-28 21:01:32 -08:00
Aotumuri 581fec5341 Fix shortcut keys being blocked by quick chat guard on attack rate bar (#2723)
Resolves #2702

## Description:

This fixes the issue reported in #2702 where certain shortcut keys
stopped working.

The root cause was the shortcut-guard logic introduced in #2528 to
prevent accidental shortcut activation while the quick chat is open.
That logic was also being applied to the attack rate bar
unintentionally, causing shortcuts to be blocked there as well.

This PR excludes the attack rate bar from the quick chat guard so
shortcuts behave correctly again.

## 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
2025-12-28 13:36:47 -08:00
Achim Marius 5a065d71c5 Fix alliance renewal popup not being removed when alliance is broken (#2722)
Resolves #2464

## Description

This PR fixes a bug where the alliance renewal popup remained visible
after an alliance was broken or betrayed.
The issue occurred because renewal UI events were tied to player
identifiers instead of the unique allianceId.
When a player had multiple alliances, breaking one alliance did not
correctly remove the associated renewal popup.
This change ensures that renewal popups are correctly removed only for
the specific alliance that was broken.


### What was wrong
Alliance renewal UI events were previously associated implicitly with
players.
This caused incorrect behavior when a player had **multiple alliances**,
because **players are not unique identifiers of an alliance**.

As a result, breaking one alliance could leave stale renewal popups
visible.

### What was changed
- Alliance break logic now relies on **allianceId**, not player IDs
- Renewal popups are removed **only for the specific broken alliance**
- Alliances involving the same player but different allianceIds are
unaffected
- Added tests to ensure this bug cannot reappear

### Result
- Renewal popup disappears immediately when an alliance is
betrayed/broken
- No unintended removal of other alliance renewal popups
- Correct behavior even when a player is involved in multiple alliances

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

assessin.
2025-12-28 13:35:05 -08:00
bijx 7284ded290 Feat: Quick donate troops via radial menu (#2708)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #2705 

## Description:

Introduces a quick donation feature in games where the `canDonateTroops`
option is enabled. It works by converting the center button in the
radial menu from a disabled attack button to a troop donate button when
the player right clicked on is friendly (teammate or ally).

Also adds donate gold button to Attack slot on radial menu when right
clicking friendly troops.

### Video Example


https://github.com/user-attachments/assets/d9b2c3f7-b6c0-482a-9dbd-b3841676cbe5

### New Icon
<img width="1310" height="931" alt="image"
src="https://github.com/user-attachments/assets/85225858-6971-470d-92f6-db68a5d05bb2"
/>

### Donate Gold


https://github.com/user-attachments/assets/b116bc06-d53d-47c7-9504-871eada6a21e


## 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
2025-12-27 13:05:02 -08:00
YoussfeCantCode 7339c968c9 uniformed HeadsUpMessage text (#2710)
## Description:

Moves pause-related translation keys from their own object into
```heads_up_message``` to keep all heads-up message text in one place.

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

furo18
2025-12-27 11:52:11 -08:00
Evan 5dc38d25f0 Add desync tracking metrics (#2707)
## Description:

- Added observable gauge to track total number of client desyncs
detected across game servers
- Tracks desyncs at the individual client level (counts each out-of-sync
client)
- Exposes metric as `openfront.desyncs.gauge` for monitoring

## 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
- [ ] 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
2025-12-26 16:10:43 -08:00
FloPinguin 5d52f73278 The clown is gone! 🤡 Nations send much better emojis now (#2696)
## Description:

Previously, nations just spammed these two rather toxic emojis: 🤡😡

They now send fewer emojis while attacking, and the clown emoji is
reserved for special cases.

They got the ability to send emojis in much more cases:
- Human didn't donate enough for relation update
- Human did donate an ok amount
- Human did donate a lot
- Responding to emojis that they get sent from a human
- Nuke sent
- MIRV sent
- Retaliation warship sent
- Traitor tries to ally
- Threat asks for / accepts an alliance request
- Disliked human tries to ally
- Friendly human tries to ally
- They are getting attacked by very much troops
- They are getting attacked by very little troops
- Congratulating the winner
- Bragging with their crown
- Charming their allies
- Clown-Emoting traitors
- Easteregg: Sending a rat emoji to very small humans

## 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: iamlewis <lewismmmm@gmail.com>
2025-12-26 13:07:31 -08:00
bibizu 664d66613b fix: Check alliance breakage once at launch, and is deterministic now (#2554)
## Description:

Removes the check to break alliance after nuke is launched, and alliance
breaking is now determined before tiles are randomly chosen for
destruction. (It is now slightly stricter, I believe, as a weighted
average calculation is a little tricky)

## 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:
bibizu
2025-12-26 12:32:16 -08:00
bijx 677a17d05a Feat: Lemnos Map (#2683)
## Description:

Introduces the Greek island, Lemnos, as a map. The island is both fun
and challenging to play (because of the terrain and elevation) and this
addition was inspired by Altis from the game [Arma
3](https://armedassault.fandom.com/wiki/Altis). The nation names are set
based on the real landmarks, towns, and regions.

<img width="2190" height="1791" alt="image"
src="https://github.com/user-attachments/assets/a7a6de54-f376-43ac-87da-f20aecfebbe0"
/>

<img width="1994" height="1608" alt="image"
src="https://github.com/user-attachments/assets/bc280780-298f-4342-8313-db6cc27ac188"
/>



## 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
2025-12-26 12:15:54 -08:00
YoussfeCantCode 1c52d20e83 Added pause functionality for private multiplayer games (#2657)
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #2491

## Description:
Adds pause/unpause functionality for private multiplayer games. Only the
lobby creator can pause the game, and all players see a pause overlay
when the game is paused.

  **Key features:**
- Lobby creator sees pause/play button in control panel (alongside
existing singleplayer/replay controls)
  - Server validates that only lobby creator can toggle pause
  - All players see "Game paused by Lobby Creator" overlay when paused
  - Game state freezes (no turn execution) while paused
  - Unpause resumes normal gameplay

  **Implementation details:**
- Server-side pause state (`isPaused`) prevents turn execution during
pause
- Each client receives `isLobbyCreator` flag in `GameStartInfo` to
show/hide pause button
- Added `TogglePauseIntent` that broadcasts to all clients via
`NoOpExecution`
  - New `PauseOverlay` component (shows in single player also)

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

furo18

<img width="1459" height="861" alt="Screenshot 2025-12-20 at 15 16 33"
src="https://github.com/user-attachments/assets/f5a3222f-f54b-473c-b0f6-104ce4c1e7a8"
/>
2025-12-26 10:21:18 -08:00
scamiv 7f3ca3c97e Update GameRenderer to disable alpha channel in GameRenderer 2D context (#2699)
## Description:

Updated the main onscreen canvas context to opaque: 
Impact: avoids alpha compositing for the main canvas (we already paint a
full opaque background each frame), which can slightly reduce GPU work.

## 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
2025-12-26 10:11:05 -08:00
scamiv 6ce6e16837 make TerrainLayer opaque (alpha:false) (#2700)
## Description:

Make the terrain backing canvas explicitly opaque by requesting a 2D
context with alpha: false.
Remove confusing latent alpha support in TerrainLayer

Current themes always generate opaque terrain colors, but the code
previously looked like it supported per-tile alpha (via
terrainColor.rgba.a), which is misleading.
Being explicit about opacity can avoid unnecessary alpha compositing
work and clarifies intent.

No visual change expected with current themes (terrain was already
effectively opaque).

## 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
2025-12-26 10:09:57 -08:00
Evan 02a6ac58ea Cleanup unused deployment secrets & args (#2698)
## Description:

* Remove unused otel creds
* Remove unused R2 creds
* remove left-over BASIC_AUTH
* Generate an admin token on startup
* Removed kick_player since lobby creators already have ability to kick
player

## 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
2025-12-25 19:38:17 -08:00
Evan 77908f7a1a Cleanup unused deployment secrets & args (#2698)
## Description:

* Remove unused otel creds
* Remove unused R2 creds
* remove left-over BASIC_AUTH
* Generate an admin token on startup
* Removed kick_player since lobby creators already have ability to kick
player

## 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
2025-12-25 19:34:36 -08:00
FloPinguin e1d0773672 Fix bots no longer attacking humans 🤖 For v28 (#2697)
## Description:

A small number of people are complaining that bots no longer attack them
and that "This has broken the factory farming strat".
In the old #2550 I somehow added that bots on easy difficulty don't
attack humans and nations anymore.
And public games are on easy difficulty now.
But I think the difficulty should actually only change nation behavior,
not bot behavior. Their attacks are harmless anyways.
So lets remove that little check.
Also let `shouldAttack()` return true for bots.

## 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
2025-12-25 16:16:13 -08:00
evanpelle 3a01e15c49 Merge branch 'v28' 2025-12-25 16:03:17 -08:00
FloPinguin 6d2ac30526 Fix bots no longer attacking humans 🤖 (#2690)
## Description:

A small number of people are complaining that bots no longer attack them
and that "This has broken the factory farming strat".
In the old #2550 I somehow added that bots on easy difficulty don't
attack humans and nations anymore.
And public games are on easy difficulty now.
But I think the difficulty should actually only change nation behavior,
not bot behavior. Their attacks are harmless anyways.
So lets remove that little check.
Also let `shouldAttack()` return true for bots.

## 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
2025-12-25 16:01:35 -08:00
Evan a9012a6613 Move cloudflare tunnel creation back into startup.sh (#2694)
## Description:
Reverts #49b01d8

Move cloudflare tunnel creation back into startup.sh. This keeps the
infra outside of the main app.
## 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:

evan
2025-12-25 13:24:23 -08:00
evanpelle fcabf49a74 Merge branch 'v28' 2025-12-25 12:49:12 -08:00
Kyriakos Dimitriou 28e22c9ca8 Improve public lobby join button UI/UX with animated three-dot indicator (#2670)
## Description:

This PR improves the public lobby join button UI by providing clearer,
state-aware feedback while a player is waiting to enter a match.

The button text now reflects two distinct phases of the join flow:
- **Waiting for players** while the lobby is filling
- **Starting game…** when the match is about to begin

This removes ambiguity caused by relying only on button color changes
and makes it immediately clear whether the join action has registered
and what stage the lobby is currently in.

### Demo
![Joining indicator
demo](https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExdWg1aXNxenI4bmI2ZjlseTVnZGRvNG1wMW9icTgyMHM1NmVjY200MSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ktmzjf0Lz55bfqbZUT/giphy.gif)

## How

- Replaces the static **“Join next game”** label with dynamic text based
on lobby state
- Shows **“Waiting for players”** with an animated three-dot indicator
while the lobby fills
- Switches to **“Starting game…”** shortly before the match begins
- Animation and state reset cleanly when leaving or cancelling
- Uses existing lobby timing and state, with no additional network calls

## Notes

- No CSS changes
- No behavioral changes to matchmaking logic
- Fully contained within `PublicLobby.ts`
- Added translation keys for the updated indicators to `en.json` (Rest
of language files will need to be updated)

## Testing notes

During local testing (single-player, local server), the button text
transitions as follows:

- Initial state (not clicked): **“Join next game”**
- After first click, the text briefly shows **“Starting game…”**
- It then switches to **“Waiting for players”** with the animated dots
- Shortly before the match starts, it switches back to **“Starting
game…”** and proceeds to start a solo game

Not sure why this flow happens in the testing environment:

**“Join next game”** ->**“Starting game…”** (brief) -> **“Waiting for
**players...”**** -> **“Starting game…”** (brief)

instead of just:

**“Join next game”** -> **“Waiting for **players...”**** -> **“Starting
game…”** (brief)

More testing is needed.

## 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
- [ ] 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
2025-12-24 10:17:22 -08:00
FloPinguin 86d1ac6c62 Nations now counter warship infestations 🚢 (#2658)
## Description:

Relevant for singleplayer and HumansVsNations: 
Humans sometimes try to flood the entire ocean with warships. The goal
is to dominate the trade and to block transport ships.

The already existing `trackTransportShipsAndRetaliate` and
`trackTradeShipsAndRetaliate` methods can't stop these large scale
infestations, the nations are completely helpless.

The new `counterWarshipInfestation` method checks if a nation is one of
the top 3 richest players (Enough money for warships) and if any enemy
(or enemy team) has accumulated more than 10 (for teams total 15)
warships, then builds a counter-warship targeting that threat.

This feature only activates on Hard or Impossible difficulty.

Thats how it can look, nations send out a warship every couple of
seconds, until the infestation threat is gone:

<img width="779" height="670" alt="Screenshot 2025-12-20 160600"
src="https://github.com/user-attachments/assets/25040077-e7db-4720-aea4-7c230afe05ea"
/>

## 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
2025-12-24 10:07:44 -08:00
bijx c77ed5f8b1 Feat: Keybind user settings directly update instruction page hotkeys (#2669)
## Description:

Currently the instructions page not only has hardcoded keybinds for the
hotkeys section, but they're also not updated (`1` and `2` are written
as decreasing and increasing attack ratio instead of `T` and `Y`). This
fix introduces a function in the `HelpModal` to get the keybinds from
the local storage and render the keys in the instructions section
dynamically. Special keys (like Arrow keys and Shift) are handled, as
well as support for the keys on a Mac computer (i.e. `⌘`).

### Video Demo


https://github.com/user-attachments/assets/2d6c6ee9-5e5d-4c7e-83df-363a345afe4d



## 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
2025-12-24 14:36:58 +00:00
VectorSophie 00babf4289 Rework fluentslider component and write tests (#2682)
## Description:

After 2 months of vacancy(my bad sorry), i have returned to end this
mess of a PR stain that i left to the codebase.
The issue is fixed, my written tests are passing, and i hand-tested and
it worked out.
Also I had to transforms Lit's ES modules into commonJS format so jest
can execute for my test,
which will indirectly enable other Lit components to be able for
testing(only my test for now)
refer to #2148 for UI stuff, nothing changed there.

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

jackochess
2025-12-24 06:24:37 -08:00
Achim Marius 0793153f4e Standardize difficulty translation keys to easy/medium/hard/impossible (#2676)
Resolves #2673

## Description:

- This PR unifies difficulty naming by switching all difficulty
identifiers to a single lowercase set of keys (`easy`, `medium`, `hard`,
`impossible`) and aligning UI + translation keys (`en.json`) to match.
- The old UI labels (`"Relaxed"`, `"Balanced"`, `"Intense"`) have been
removed and replaced with the standardized difficulty terms (`Easy`,
`Medium`, `Hard`).

<img width="1312" height="306" alt="image"
src="https://github.com/user-attachments/assets/a59c5fae-f435-427d-b851-eef179a1e94f"
/>


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

assessin.
2025-12-24 03:34:00 +00:00
FloPinguin 6afaf932a5 Make easy and medium nations less aggressive 📊 (#2671)
## Description:

1. Players complained that they have problems allying with nations in
the earlygame. So I added an `isEarlygame()` check to
`AllianceBehavior`. This should make the easier difficulties much easier
:)

2. The attack order of nations now depends on the difficulty. Easy and
medium nations got dumbed down, they now take nuked territory before
retaliating against attacks again.

3. The attack rate now depends on the difficulty. Easy nations are
reacting slower than impossible nations (to make sure the number of sent
alliance requests stays the same I removed the difficulty check in
`maybeSendAllianceRequests()`).

4. On easy and medium difficulty nations will sometimes just skip an
attack if the enemy is a human (`shouldAttack()`). But this did not
apply for the nuking logic. Now it does, which makes the easier
difficulties a bit easier.

5. I tuned the `getBotAttackMaxParallelism()` method a bit. The nations
are doing a bit less parallel bot attacks now, which makes the easier
difficulties a bit easier.

6. The settings in MIRVBehavior now depend on the difficulty. On easy
difficulty, nations will only send MIRVs very rarely.

7. Unrelated MIRVBehavior Cleanup: There was a 2 second cooldown and
cache logic. But it was completely useless because `considerMIRV()` is
only called every 4-8 seconds by NationExecution. So I removed it.

8. Unrelated little cleanup: I made a couple of methods `private`

## 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
2025-12-24 03:10:39 +00:00
Mykola 56e497145e Fix nations spawn (#2672)
## Description:

Returned code that spawns nations around predefined coordinates from the
map manifest.

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

nikolaj_mykola
2025-12-24 03:07:51 +00:00