## Description:
A new map where you basically have to hop from island to island :)
We don't have such a map at the moment.
There is a special center island which isn't necessary to get 80% of the
map.
This map could be very interesting in team games. One hydro will destroy
an entire island.
Size: 1976 x 1976
Nations: 8
<img width="949" height="951" alt="Screenshot 2026-01-02 214219"
src="https://github.com/user-attachments/assets/7139bcc9-6a05-414d-90c1-33cc36dd94fb"
/>
## 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
## Description:
`MIRVExecution.separate` is consuming more resources than it needs to.
This PR introduces a series of minor performance changes which do not
alter the behavior of the selection algorithm. Assessing the code
initially, I was convinced there are multiple easy wins - starting with
the proximity check. However, after many hours of mostly math, no
alternative solution came close to the speed of current implementation.
Therefore this PR consists of only a few minor tweaks:
#### Removed `console.log`
This is by far the worst offender, in my test removing the three lines
of console log improved execution time from ~30ms down to ~10ms. The
logs are not very useful. I do not see a clear pattern in the logs
produced by the application therefore they were completely removed for
now. If there is a need for the log in production build, I suggest
adding single line with the number of destinations selected.
```diff
- console.log(`dsts: ${dsts.length}`);
- console.log(`got ${dsts.length} dsts!!`);
- console.log("couldn't find place, giving up");
```
#### Replaced multiple calls to `random.nextInt` with single call to
`random.next`
The flamechart shows calling pseudo random number generator is
expensive. Therefore instead of calling it twice, the code now generates
a single random number and derives further calculations from it. It
remains 100% deterministic and there should not be any noticeable change
to the enthrophy. This saves about ~1.5ms in my tests.
```diff
- const x = this.random.nextInt(
- this.mg.x(ref) - this.mirvRange,
- this.mg.x(ref) + this.mirvRange,
- );
- const y = this.random.nextInt(
- this.mg.y(ref) - this.mirvRange,
- this.mg.y(ref) + this.mirvRange,
- );
+ const r1 = this.random.next();
+ const r2 = (r1 * 15485863) % 1;
+ const x = Math.round(r1 * this.range * 2 - this.range + this.baseX);
+ const y = Math.round(r2 * this.range * 2 - this.range + this.baseY);
```
#### Caching of destination coordinates
Since the target tile coordinates are used a lot, instead of retrieving
them every time with `this.mg.x` and `this.mg.y`, they get cached as
`baseX` and `baseY`. To reduce usage further, I also exposed `x` and `y`
to `isOverlapping` / `proximityCheck` directly instead of passing the
tile. Since available methods operate on `TileRef`, this change requires
the calculations - manhattan and euclidean distance - to be inlined. I
do not think this is a big issue, considering this code is responsible
for very specific task. This saves another ~1.5ms in my tests.
```diff
- if (this.mg.euclideanDistSquared(tile, ref) > mirvRange2) {
+ if ((x - this.baseX) ** 2 + (y - this.baseY) ** 2 > this.rangeSquared) {
```
## Benchmark:
**Before**
```
=== MIRV Performance Benchmark Results ===
MIRV target selection - sparse territory x 53.53 ops/sec ±0.48% (71 runs sampled)
MIRV target selection - dense territory x 53.39 ops/sec ±0.57% (70 runs sampled)
MIRV target selection - giant world map (350 targets) x 1,129 ops/sec ±0.98% (90 runs sampled)
```
**After**
```
=== MIRV Performance Benchmark Results ===
MIRV target selection - sparse territory x 198 ops/sec ±0.39% (85 runs sampled)
MIRV target selection - dense territory x 200 ops/sec ±0.28% (86 runs sampled)
MIRV target selection - giant world map (350 targets) x 1,409 ops/sec ±0.89% (92 runs sampled)
```
## 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
- [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
\* Tests in separate PR, implemented against master:
https://github.com/openfrontio/OpenFrontIO/pull/2767
## Please put your Discord username so you can be contacted if a bug or
regression is found:
moleole
Fixes#2758
## Description:
This PR migrates lobby configuration updates from the HTTP PUT
`/game/:id` endpoint to a WebSocket-based intent flow.
The lobby creator is already authenticated via the game WebSocket, so
updating configuration through intents removes redundant authentication
and aligns with existing real-time lobby actions such as `kick_player`
and `toggle_pause`.
## Changes Made
- Added `update_game_config` WebSocket intent schema
- Wired client → transport → server intent handling
- Refactored `putGameConfig()` to emit WebSocket intent instead of HTTP
fetch
- Preserved all existing validation, partial-update semantics, and
client-side debouncing
- Left the REST endpoint untouched for backward compatibility
## Testing
- All existing automated tests pass
- Manual verification completed:
- Lobby creator can update all lobby settings
- Non-creators are rejected
- Updates are rejected after game start
- Bots slider debounce (300ms) remains intact
- No `PUT /api/game/:id` requests are made from the lobby UI
## Checklist:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## 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
## 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
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>
## 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
## 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
## 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>
## 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
## 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>
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>
- 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>
## 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>
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.
## 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>
## 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
## 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
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"
/>
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## 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
## Description:
SAMs will now always hit their target instead of missing sometimes.
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:
Lavodan
## Description:
Add visual indicators to territory borders that reflect diplomatic
relationships between players, making it easier to identify relations at
a glance.
### Problem Statement
Currently, players must check diplomatic status through other UI
elements. There's no immediate visual feedback on the map showing which
borders represent embargo or friendly relationships.
### Benefits
1. **Improved Gameplay Clarity**: Quickly identify diplomatic
relationships without opening menus
2. **Strategic Awareness**: Visual feedback helps make tactical
decisions about border defense
### Proposed Solution
Tint territory borders based on neighbor relationships: embargo red,
friendly green
### Implementation Details
- Border variants are based on this._borderColor (theme/style handling
unchanged) computed in the constructor and stored in userSettings
UnitView
- Apply tinting to checkerboard for defended borders
- borderColor() checks all neighbors to determine the worst relationship
status
- Embargos take priority.
<img width="1193" height="601" alt="image"
src="https://github.com/user-attachments/assets/cb516402-4f4b-473c-a31b-02397fee9203"
/>
<img width="959" height="682" alt="image"
src="https://github.com/user-attachments/assets/de01a4b9-0fd4-44b2-895d-96705b6cf30b"
/>
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Description:
SAMs will now always hit their target instead of missing sometimes.
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:
Lavodan
Resolves#2602
## Description:
tldr: `npm run docs:map-generator`
Adds documentation to the `map-generator` go code.
This has no functional changes, other than the renaming of the package.
I used the github url, though this can be set to anything as long as it
contains a `.` so that the docs parse it correctly. Go doc best
practices seem a little verbose and terse, but attempted to comply
Future Facing (to get these docs viewable without running locally):
- Wait until the -http issue is sorted, then these are easy to
statically host alongside builds
- Could use the legacy `godoc`
- Could do formatting after outputting the `txt` output
## Change List:
- Add documentation to all types/fns in map-generator go code
- Ensure this outputs correctly with `go doc`
- Add `docs:map-generator` command to package.json. This runs `go doc`
in `map-generator` w/ appropriate flags to generate full documentation.
(see notes in readme)
- rename `map-generator` module to work around pkgsite assuming all
packages without a . are stdlib (this makes `-http` work at all)
- Add new sections to README and update existing sections
- Add additional references to locations in the primary code base where
things can be found
- Update documentation in the ts theme files to add output color
mappings - this ensures that everything needed to trace the input file
-> in game rendered asset is fully documented.
## 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:
tidwell
## Description:
Saw lots of `"cannot send ship to Player"` warnings in the console.
It was caused by `randomBoatTarget` not checking if the target is
reachable by boat.
It also caused the for loop in `randomBoatTarget` to exit too early (=>
no boat sent).
So I added a `canBuildTransportShip` check. Because this runs expensive
(?) pathfinding I added a `unreachablePlayers` Set to optimize
performance.
## 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
## Description:
This is a previously approved PR with an additional commit that fixes
case when nations change spawn & jump around, their previous territory
wasn't getting deleted.
## 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
---------
Co-authored-by: Evan <evanpelle@gmail.com>
## Description:
Following the hotkey cursor price textbox addition of #2650, this
feature adds the option to enable and disable the visual feature via the
User Settings menu or the Basic Settings modal in game. Also added a
[new icon](https://thenounproject.com/icon/pay-per-click-2586454/) for
the Basic Settings modal from the Noun Project and added credit for it
to the `CREDITS.md` file.
### Video Demo
https://github.com/user-attachments/assets/1667081e-45e3-4b11-9bda-3f00c341e03c
### User Settings Menu
<img width="1029" height="1436" alt="image"
src="https://github.com/user-attachments/assets/e4e6bf6d-db59-463a-81fb-f622ef6e3931"
/>
### Basic Settings Menu
<img width="964" height="1545" alt="image"
src="https://github.com/user-attachments/assets/6b083655-b96e-4937-95d6-f3458858f03d"
/>
## 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
## Description:
This PR removes the nation strength. Reasoning:
- It is currently unused. The backstory can be found in #2498
- It forces map-makers to do balancing work, which is probably not a
good idea
- It increases map-making work
- It increases nation balancing complexity by a lot (we need to have all
the json files in mind)
- It makes humans avoid map areas completely because there is always
that one, same, strong nation
- The map lead Nikola123 wants to "not deal with the stupid nations and
their balancing"
If the goal of nation strength was to make them feel different I would
suggest a nation personality system. Nations that love to boat, love to
ally, love to nuke, love to fullsend, etc.
Link to a discord discussion about nation strength:
https://discord.com/channels/1359946986937258015/1360078040222142564/1450973197251117218
## 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
## Description:
1. Moved the currently very small betrayal logic from `AiAttackBehavior`
to `NationAllianceBehavior` because it makes more sense to have it
there.
3. Very small bugfix in `AiAttackBehavior::shouldAttack()`: the numbers
in the two `random.chance` calls were the wrong way round.
4. `NationExecution` was quite big and a lot of it was about MIRVs. So I
moved all the MIRV logic to the new `NationMIRVBehavior`.
5. `emoji()` and `maybeSendEmoji()` did not really fit in
`AiAttackBehavior`. So I moved it to the new `NationEmojiBehavior` (and
did some renaming for clarity). I'm planning to extend that class in a
future PR.
2. Reordered methods in `AiAttackBehavior` to easily find related
methods.
6. Reordered methods in `NationExecution` to easily find related
methods.
## 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
## Description:
1. Using the wording `"Nation"`, `"FakeHuman"` and `"NPC"` at the same
time is confusing.
So I renamed every mention of `"FakeHuman"` and `"NPC"` in the entire
project to `"Nation"`. Just like they are called ingame.
2. `BotBehavior.ts` was originally intended for sharing the logic
between nations and bots.
But at the moment, the logic there isn't really shared and it's
basically just about attacking.
So I renamed `BotBehavior.ts` to `AiAttackBehavior.ts`. I use "Ai" to
indicate that this file is used by bots AND nations.
3. Moved `execuction/utils/AllianceBehavior.ts` to
`execuction/nation/NationAllianceBehavior.ts` to make sure everybody
understands that this file is not about alliances in general. It's just
about nations and how they handle alliances.
4. Removed `difficultyModifier` from `DefaultConfig`. It's unused and I
think we usually want to finetune the difficulty instead of using that
method.
5. Added `assertNever` in all `switch (difficulty)` default cases.
## 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
## Description:
Add some christmas spirit in the emoji list
🎁🌟🎅🎄⛄
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
IngloriousTom
## Description:
Saw this in an Enzo video about beating impossible nations:
You can just donate 1% gold / 1% troops to a nation to get a friendly
relation with them.
This PR adds randomized minimum donation requirements based on the
difficulty.
Randomized in a way that there is a minimum someone has to donate to
surely get the relation improvement, but you can also gamble and send
less.
For troop donations, the minimum is calculated based on what percentage
of their troops the sender donated.
For gold donations, it's fixed values. We cannot use percentages here
because “having nearly no gold” is a usual case. Donating 100% of your
gold wouldn’t hurt if you just spent all your gold on buildings.
I tried to add tests for this but it's really horrible. Because the test
would have to wait until the relation update from the alliance accepting
is gone (we need to have an alliance to send stuff), has returned to
Neutral, and then changes back to Friendly after the donation.
## 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: Evan <evanpelle@gmail.com>
## Description:
This PR centralizes all username validation using UsernameSchema with a
set maximum, minimum, and a regex pattern,
It also removes sanitization, as all places where the username would be
sanitized on the server have been gatekept, so no unvalidated usernames
can get onto the server past the ClientMessageSchema safeParse in
GameServer's on message func.
Here is how the errors look if that happens, Note that if the client is
funtioning correctly and the user doesn't manually send a WS message,
they should never see this. The screenshots are from a debug build where
client uname validation was disabled.
<img height="300" alt="error message too short"
src="https://github.com/user-attachments/assets/1b7ac32c-2f03-40fb-8ce9-1f4ab66100bd"
/>
<img height="300" alt="error message bad regex"
src="https://github.com/user-attachments/assets/c78b4114-7e4b-4d39-a135-4cab3ad52c0b"
/>
Profanity sanitization was not changed.
Additionally, the censor tests were updated to reflect the new
expectations.
Jose was added to the jest config as an allowed transform pattern, as it
didn't make sense to me to mock a zod schema.
The UsernameSchema pattern was set to `^[a-zA-Z0-9_ \[\]üÜ]+$`, I
personally think either we should allow all latin characters (regex has
a pattern for this, `\p{L}` or `\p{sc=Latin}`) and then we'd use some
kind of library to normalize all latin characters into regular ascii for
name filtering, or we should only keep ascii letters.
## 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:
Lavodan
(I just realized sanitization isn't a word, it's supposed to be
sanitation, sorry.)
## Description:
Adds a map based on the Manicouagan Reservoir in Quebec and credits
OpenTopography
## Checklist:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
<img width="1017" height="1017" alt="Screenshot 2025-12-14 214706"
src="https://github.com/user-attachments/assets/030c4bbd-0325-4da4-bef5-71053dc8f183"
/>
## Discord username:
sehentsin
## Description:
To prevent MAD stalemates, have the price of MIRVs increase after each
launch. This will encourage players to launch a MIRV once they have
enough money for it. Also reduce the price of the first MIRV to 25
million to reduce snowballing, each subsequent MIRV cost an extra 15
million:
1. 25 million
2. 40 million
3. 60 million
4. etc
## 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