Commit Graph

2975 Commits

Author SHA1 Message Date
Ryan 853041e9a1 Merge branch 'main' into bomb-confirmation 2026-01-08 00:40:06 +00:00
evanpelle 81ae714533 Revert "Allow NUM_WORKERS override (#2776)"
This reverts commit 3cd22745f7.

num_workers was not passed to the client
2026-01-07 16:16:58 -08:00
Aotumuri 3cd22745f7 Allow NUM_WORKERS override (#2776)
Resolves #2610

## Description:

Add NUM_WORKERS env override for server worker count.

## Please complete the following:

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

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

---------

Co-authored-by: Evan <evanpelle@gmail.com>
2026-01-06 19:40:00 -08:00
FloPinguin ebcb654825 Added a public game modifier system 😮 For more variety (#2801)
## Description:

Added a public game modifier system. It causes that

5% of public games are played on the compact version of the map
10% of public games have "Random Spawn" activated

Percentages can easily get changed via `DefaultConfig`.
We can also easily add more modifiers.
Modifiers can stack, so in rare cases you will play on a compact map
with random spawn 😄
More variety!

### "Compact Map" modifier implementation

- With the "Compact Map" modifier the lobby max player count gets
reduced to 25% and only 25% of the regular bots and only 25% of the
regular nations will spawn (because the map has only 25% of its regular
size)
- In private lobbies and singleplayer the nation reduction happens too
(When "Compact Map" is enabled).

### Restrictions

- Duos/Trios/Quads team modes do not get Random Spawn (defeats the
purpose)
- Maps with smallest player count < 50 do not get Compact Map in team
games (not enough players after the reduction to 25%). I have calculated
all the possible max player counts.

### How it looks like

Random Spawn modifier:

<img width="528" height="183" alt="Screenshot 2026-01-06 194959"
src="https://github.com/user-attachments/assets/2f729da9-80c3-4548-8205-71129da2a76a"
/>

Very rare case: Two modifiers at the same time and only 10 max players
have been chosen from `[GameMapType.FaroeIslands]: [20, 15, 10]`.
Because of the 75% reduction in player count only 3 players are allowed
(3 is the minimum). I think its funny that you can play a 1v1v1 in rare
occasions 😄

<img width="526" height="184" alt="Screenshot 2026-01-06 194938"
src="https://github.com/user-attachments/assets/834326eb-df03-41b7-b1db-1efa3f1013b5"
/>

### Funny side-effect

Team games with random spawn. That will be interesting. No more "Who is
better in donating troops to the frontline". Instead you have to heavily
coordinate with your teammates.

## 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-06 19:37:58 -08:00
FloPinguin 387190b916 New map! "Amazon River" 🏞️ (#2798)
## Description:

We didn't have a river map and we didn't have a map with a crazy size.
So I made a "Amazon River" map with a crazy size.
280 x 5536!
21 nations based on real locations.
Should be interesting gameplay because you don't have many attack
options, your only escape is the river.
The land tiles size is similar to the achiran and iceland map.

<img width="2442" height="147" alt="Screenshot 2026-01-06 150831"
src="https://github.com/user-attachments/assets/91c4142d-c1e3-4aee-ac49-529b8d9f60c4"
/>

<img width="2324" height="139" alt="Screenshot 2026-01-06 150957"
src="https://github.com/user-attachments/assets/5e049ae5-f32a-495f-afde-9e20257b3676"
/>

Because the map is so wide, it looked really ugly stretched in the
thumbnails. So I added some CSS which removes the thumbnail stretching
of the Amazon River map. We can also use this logic for other thumbnails
which shouldn't get stretched.

In `Maps.ts`, `PublicLobby.ts` and `GameInfoModal.ts`.

## 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-06 19:34:02 -08:00
Wraith ae5c111282 fix(build): remove old configration files for postcss and tailwind in (#2803)
## Description:

fix(build): remove old configration files for postcss and tailwind in
docker builds and eslint config

## 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
2026-01-06 19:31:26 -08:00
aConifer effce3d14a add teammate pulse highlight during spawn phase in team games (#2768)
Adds a pulsing highlight effect for teammates during the spawn phase in
team games. This helps colorblind players identify their teammates on
the map more easily.

- Teammates show a subtle green/team-colored pulse (5-14px radius)
- Player's own pulse remains unchanged (8-24px white pulse)
- Only activates during spawn phase in team games
- Animation stays synchronized with player's own pulse

I didn't want to come empty handed with my request so I generated the
code
I do know python and a little rust, but don't have TypeScript experience
- I know you guys are probably getting flooded with AI slop so I hope
its okay.
Please implement the feature at the very least because its SO much
better not having to hunt around.
🤖 Generated with [Claude Code](https://claude.com/claude-code)

So the code calls drawTeammateHighlights() inside of
drawFocusedPlayerHighlight() so it can only occur where current
highlighting occurs
Then uses the existing isOnSameTeam() to find teammates
Then uses the existing drawBreathingRing() function 


- [x] I have added screenshots for all UI updates
I took a video since it best captures the feature
- [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'm not that good at coding formally, I tested it manually by loading
into team games, but I'm going to need help with the code being tested.
(Please help)
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
I did load into multiple lobbies and made sure the feature works, its a
really simple feature so I am confident there isn't any Lovecraftian bug
lurking in it. It also uses mostly existing functions and features
within the code base.




https://github.com/user-attachments/assets/857cce43-4fb2-4c5d-bc04-1a6617570dee

Co-authored-by: Daniel <daniel@mangoit.ca>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
2026-01-06 14:22:57 -08:00
Wraith e79c805804 refactor(ui): migrate tailwindcss v3 to v4 (#2735)
## Description:

migrate tailwindcss v3 to v4

## 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: iamlewis <lewismmmm@gmail.com>
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
2026-01-06 14:21:52 -08:00
evanpelle 24716f848d bugfix: hide language button when starting game 2026-01-06 09:33:25 -08:00
FloPinguin 69fe93f6ff Fix little translation problem "host_modal.bots" (#2799)
## Description:

Fixes this:

<img width="1485" height="960" alt="image"
src="https://github.com/user-attachments/assets/fa27b2da-fe2c-4423-9f25-3051b93de77b"
/>

## 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-06 08:23:13 -08:00
Ryan 033b5c2bab Merge branch 'main' into bomb-confirmation 2026-01-06 15:03:26 +00:00
Evan 38f8c6b995 Move language button to bottom left (#2796)
## Description:

Move the language button to the bottom left so it takes up less space.

<img width="615" height="567" alt="Screenshot 2026-01-05 at 5 54 23 PM"
src="https://github.com/user-attachments/assets/f29d5bcb-8627-493a-8c0f-1966cb9c9be6"
/>

## Please complete the following:

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

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

evan
2026-01-05 17:57:26 -08:00
bijx b9f4a8d77b Feat: Singleplayer Achievements (#2734)
Contributes towards the ongoing task of adding achievements: #2706

## Description:
Introduces a concept design and API implementation for singleplayer win
achievements. New row of ~5~ 4 medals is added to the map select screen
in the Singleplayer modal, one for each difficulty:
<img width="3132" height="779" alt="image"
src="https://github.com/user-attachments/assets/da8f0314-ccad-4f45-a03f-1beb46981301"
/>

In order to achieve a medal in a particular map, you must win the
singleplayer game (multiplayer and private match games don't count) in
the selected difficulty **without tampering with the options or
settings**. If any setting is changed from the default, regardless of
the difficulty, you will ~receive a fifth "Custom" medal~ not receive
the medal for that difficulty. Team games **do not** count towards the
medal achievement.

Completion of a medal will fill in the full correct color, as defined in
our `variables.css`:
<img width="694" height="778" alt="image"
src="https://github.com/user-attachments/assets/1b2d8370-aa86-4329-9402-adf43f3ef799"
/>

Completion medals can be toggled on or off (hidden by default) with the
toggle button at the top of the section:


https://github.com/user-attachments/assets/d08a58e0-b534-430e-9e8f-559134ad8852


[API implementation PR](https://github.com/openfrontio/infra/pull/234)

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

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
Co-authored-by: Evan <evanpelle@gmail.com>
2026-01-05 16:27:36 -08:00
FloPinguin ecc174d248 New map! "Didier" 🧸 (#2794)
## Description:

Didier map for the big french youtuber Fuze which already published
several OpenFront videos.
I took the real france, cut away the bordering countries and made it
look like Didier 😄
Gave it eyes, hands and feet.
Made sure we have some rivers, also put Corsica in the right bottom
corner!
It's quite large. Similar to the europe map. Has 42 nations (38 french
cities and 4 funny custom nations for the youtuber).
Made with [TsProphets map
generator](https://github.com/TsProphet94/OpenFrontMapGenerator), QGIS
and GIMP.
For public games I put a rare map frequenzy of 2 because most people
probably don't know Fuze.

@ibnhalwa from discord gave some insider knowledge about Fuze (He's
french, I'm not).

<img width="2100" height="2250" alt="image"
src="https://github.com/user-attachments/assets/5d1c3c45-4b2e-4f60-a02f-89b26f938652"
/>

<img width="1278" height="1218" alt="Screenshot 2026-01-05 184540"
src="https://github.com/user-attachments/assets/6e300bb0-6e9f-4b0f-bad8-94f031d250b1"
/>


![1_1200x1200_crop_center](https://github.com/user-attachments/assets/09b2aca7-32be-4ddc-9638-de7fe8c9f30c)

## 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-05 16:19:13 -08:00
Ryan 19f2d22c4f Merge branch 'main' into bomb-confirmation 2026-01-05 17:44:13 +00:00
FloPinguin f73953c240 ☢️ Nations send much better nukes now (Part 2) ☢️ (#2779)
## Description:

### Refactor

- Moved `findBestNukeTarget()` (and child methods) from
`AiAttackBehavior` to `NationNukeBehavior` because it makes more sense.
- `NationNukeBehavior`: Renamed `mg` to `game` (So its similar to the
other nation .ts files)
- Moved the `removeOldNukeEvents()` method a bit

### New features

- Impossible difficulty nations are now optimized for SAM outranging!
- 1 of 3 nations is now a hydro-nation. They cannot send atom bombs.
They save up for hydros. This is to reduce atom-bomb-spam on the map.
- On impossible difficulty, the crown nukes the second place now (in
FFAs)
- On hard and impossible difficulty, nations now ignore the perceived
cost for nukes if they get heavily attacked. Reasoning: They should stop
saving for MIRV, they should defend with all their gold!
- On medium, hard and impossible difficulty, nations no longer throw
nukes at places where another team member already has a nuke "in the
flying process"
- Optimized `lastNukeSent` a bit (to respect nuke radius)
- Adjusted `maybeSendNuke()` to use 30 instead of 10 randomTiles on
impossible difficulty to improve chances of finding a perfect SAM
outranging spot
- On impossible difficulty, nations now ignore their "most hated enemy"
if the crown has 50%+ of the map (Very big danger). Instead they are
nuking the crown.
- Added `isFriendly` check to `findStrongestTeamTarget()`

### Media

SAM outranging:


https://github.com/user-attachments/assets/d1e88bb6-0060-400b-9c16-24d7399f5949

Team game nukes not hitting the same spot:

<img width="1160" height="708" alt="Screenshot 2026-01-03 042236"
src="https://github.com/user-attachments/assets/c017fb3c-3e3f-45fb-9d45-dd4caba7a59f"
/>

## 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-04 22:28:33 +00:00
Ryan 76eebdda5e Merge branch 'main' into bomb-confirmation 2026-01-04 14:51:43 +00:00
FloPinguin 6d1e2f59de Optimize player count configuration for Surrounded map 🏝️ (#2780)
## Description:

Based on Nikola map lead feedback

## 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-03 20:07:30 -08:00
VectorSophie 70767d2541 Fluentslider rapid-fire bug fix (#2778)
## Description:

Describe the PR.

Modified FluentSlider(my code) to split number input handle to visual
update(NumberInput) and dispatch value(NumberComplete)

updated the event flow to match them, will fix rapid-fire updates that
seemed to glitch bots out.

## 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
2026-01-03 20:07:13 -08:00
DevelopingTom af0b8a8d50 Configurable immunity timer (#2763)
## Description:

Resolve discussions about stalled PR
https://github.com/openfrontio/OpenFrontIO/pull/2460

<img width="724" height="348" alt="image"
src="https://github.com/user-attachments/assets/c2c9fa79-cace-431a-9ca4-b3656612fa9d"
/>

Changes:
- Added a `Player::canAttackPlayer(other)` function to determine whether
a player can be attacked.
- This function is now used in most places where a fight can occur:
    - AttackExecution (land attacks)
    - Naval invasion
    - Warship fight
- Nukes can't be thrown during the truce
- Immunity only affect human players. Nations and bot will fight as
usual, and can be fought against.
- The immunity timer uses minutes in the modal window.

UI:

- The immunity phase is displayed with a timer bar at the top. This is
from the original PR, to be discussed if it's not deemed visible enough:

<img width="632" height="215" alt="image"
src="https://github.com/user-attachments/assets/f5ab9aa0-bd4f-4503-b8d6-b40b121fba65"
/>


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

---------

Co-authored-by: newyearnewphil <git@nynp.dev>
2026-01-03 20:04:48 -08:00
Ryan Barlow 28283ba8bd updated test 2026-01-03 22:13:14 +00:00
Ryan Barlow 2d11cf5bb2 add docs 2026-01-03 22:05:46 +00:00
Ryan Barlow 0022b8cc01 Added accessible labels to the ghost control buttons 2026-01-03 22:03:42 +00:00
Ryan Barlow b41e8b832a Only updates the controls’ styles when those values change; otherwise skips DOM writes 2026-01-03 22:02:58 +00:00
Ryan Barlow 863e7ca573 Added coverage for the new nuke selection flow and updated mocks 2026-01-03 21:46:10 +00:00
Ryan Barlow ff23e9527c Consolidated the duplicate tile lookup into a single getTileFromScreenCoords(x, y) 2026-01-03 21:45:00 +00:00
Ryan Barlow 102cd5cb56 Extracted shared target resolution logic into getTargetTile() 2026-01-03 21:44:16 +00:00
Ryan Barlow e702c7dc23 maximise the button 2026-01-03 21:42:34 +00:00
Ryan 13704a6e49 Update src/client/graphics/layers/NukeTrajectoryPreviewLayer.ts
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-03 21:16:04 +00:00
Ryan 4af650f1b6 Update src/client/graphics/layers/NukeTrajectoryPreviewLayer.ts
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-03 21:15:55 +00:00
Ryan Barlow acfb48f0f6 Added mobile zoom suppression 2026-01-03 20:59:24 +00:00
Ryan Barlow 342a712ddc make buttons html again 2026-01-03 20:52:49 +00:00
Ryan Barlow f7fc652026 InputHandler now ignores pointer down/up when this flag is true, preventing drag/pan or ghost moves while clicking the controls. 2026-01-03 20:49:43 +00:00
Ryan Barlow c8509a77ac prevent the radial menu from showing when there's a locked bomb 2026-01-03 20:38:15 +00:00
Ryan Barlow a60bb5c7c1 Prevent ContextMenuEvent emission in InputHandler when there's a locked bomb
Convert DOM buttons to PIXI Graphics elements that are part of the ghostStage
2026-01-03 20:31:38 +00:00
Ryan Barlow c496af24d3 disable radial menu when bomb menu open 2026-01-03 20:17:15 +00:00
Ryan Barlow 42927609c3 Removed the misleading hideGhostControls() wrapper method 2026-01-03 20:10:34 +00:00
Ryan Barlow d05e6af733 use emojis instead 2026-01-03 20:09:14 +00:00
Ryan Barlow e85753403d listen to ContextMenuEvent instead of MouseUpEvent when a locked bomb is active 2026-01-03 20:07:54 +00:00
Ryan Barlow ec0a0df046 offset the buttons to below the bomb radius by 1px 2026-01-03 20:03:58 +00:00
Ryan Barlow 6623b7f503 update test 2026-01-03 19:33:12 +00:00
Ryan Barlow 41e5adf1fe initial test 2026-01-03 19:27:21 +00:00
Arkadiusz Sygulski ab5b044362 Fix train was destroyed message spam (#2774)
## Description:

Trains are made of a primary unit (`TrainExecution.train`) followed by 6
cars (`TrainExecution.cars`). Currently when any of the units is
destroyed, a message "Your Train was destroyed" is shown. In worst case
scenario, when all cars are blasted by a nuke, 7 messages are displayed
to the user, but the train continues.

Since the actual logic is unaffected as long as the primary unit stays
alive, displaying messages is confusing. This PR fixes it. The message
is only displayed when the primary unit is destroyed. The following cars
are only there for fancy visuals.



## Screencast

##### Current - multiple messages for single train


https://github.com/user-attachments/assets/3df04c71-d899-4f68-af83-36c9d0ffa730

First nuke was a test.
Second nuke destroyed the entire train, prompting 7 messages.
Third nuke destroyed one full train and then some. Prompting many too
many messages.

##### Fixed - one message, only if train was fully destroyed


https://github.com/user-attachments/assets/1f3840a7-6c62-487d-af3a-82de39dad9e8

First train was only partially destroyed, no message was shown, delivery
mission completed A+.
Following 2 trains had the front engine destroyed and therefore were
promptly decommissioned.

## Please complete the following:

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

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

moleole
2026-01-02 18:53:24 -08:00
Aotumuri ae6293f6da Add language metadata and enhance language validation tests (#2748)
Resolves #2739

## Description:

Introduce language metadata handling and refactor existing language
checks to validate the existence of language JSON and corresponding SVG
files. Add tests to ensure the integrity of the new metadata structure
and its references.

The lang field is intentionally kept in each language file.
This is because the files are frequently regenerated by Crowdin, and the
field also serves as a hint for management and maintenance.

## Please complete the following:

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

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

aotumuri

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-02 18:45:49 -08:00
dependabot[bot] d9ccb0ea16 Bump qs from 6.13.0 to 6.14.1 in the npm_and_yarn group across 1 directory (#2753)
Bumps the npm_and_yarn group with 1 update in the / directory:
[qs](https://github.com/ljharb/qs).

Updates `qs` from 6.13.0 to 6.14.1
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ljharb/qs/blob/main/CHANGELOG.md">qs's
changelog</a>.</em></p>
<blockquote>
<h2><strong>6.14.1</strong></h2>
<ul>
<li>[Fix] ensure arrayLength applies to <code>[]</code> notation as
well</li>
<li>[Fix] <code>parse</code>: when a custom decoder returns
<code>null</code> for a key, ignore that key</li>
<li>[Refactor] <code>parse</code>: extract key segment splitting
helper</li>
<li>[meta] add threat model</li>
<li>[actions] add workflow permissions</li>
<li>[Tests] <code>stringify</code>: increase coverage</li>
<li>[Dev Deps] update <code>eslint</code>,
<code>@ljharb/eslint-config</code>, <code>npmignore</code>,
<code>es-value-fixtures</code>, <code>for-each</code>,
<code>object-inspect</code></li>
</ul>
<h2><strong>6.14.0</strong></h2>
<ul>
<li>[New] <code>parse</code>: add
<code>throwOnParameterLimitExceeded</code> option (<a
href="https://redirect.github.com/ljharb/qs/issues/517">#517</a>)</li>
<li>[Refactor] <code>parse</code>: use <code>utils.combine</code>
more</li>
<li>[patch] <code>parse</code>: add explicit
<code>throwOnLimitExceeded</code> default</li>
<li>[actions] use shared action; re-add finishers</li>
<li>[meta] Fix changelog formatting bug</li>
<li>[Deps] update <code>side-channel</code></li>
<li>[Dev Deps] update <code>es-value-fixtures</code>,
<code>has-bigints</code>, <code>has-proto</code>,
<code>has-symbols</code></li>
<li>[Tests] increase coverage</li>
</ul>
<h2><strong>6.13.1</strong></h2>
<ul>
<li>[Fix] <code>stringify</code>: avoid a crash when a
<code>filter</code> key is <code>null</code></li>
<li>[Fix] <code>utils.merge</code>: functions should not be stringified
into keys</li>
<li>[Fix] <code>parse</code>: avoid a crash with
interpretNumericEntities: true, comma: true, and iso charset</li>
<li>[Fix] <code>stringify</code>: ensure a non-string
<code>filter</code> does not crash</li>
<li>[Refactor] use <code>__proto__</code> syntax instead of
<code>Object.create</code> for null objects</li>
<li>[Refactor] misc cleanup</li>
<li>[Tests] <code>utils.merge</code>: add some coverage</li>
<li>[Tests] fix a test case</li>
<li>[actions] split out node 10-20, and 20+</li>
<li>[Dev Deps] update <code>es-value-fixtures</code>,
<code>mock-property</code>, <code>object-inspect</code>,
<code>tape</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ljharb/qs/commit/3fa11a5f643c76896387bd2d86904a2d0141fdf7"><code>3fa11a5</code></a>
v6.14.1</li>
<li><a
href="https://github.com/ljharb/qs/commit/a62670423c1ccab0dd83c621bfb98c7c024e314d"><code>a626704</code></a>
[Dev Deps] update <code>npmignore</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/3086902ecf7f088d0d1803887643ac6c03d415b9"><code>3086902</code></a>
[Fix] ensure arrayLength applies to <code>[]</code> notation as
well</li>
<li><a
href="https://github.com/ljharb/qs/commit/fc7930e86c2264c1568c9f5606830e19b0bc2af2"><code>fc7930e</code></a>
[Dev Deps] update <code>eslint</code>,
<code>@ljharb/eslint-config</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/0b06aac566abee45ef0327667a7cc89e7aed8b58"><code>0b06aac</code></a>
[Dev Deps] update <code>@ljharb/eslint-config</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/64951f6200a1fb72cc003c6e8226dde3d2ef591f"><code>64951f6</code></a>
[Refactor] <code>parse</code>: extract key segment splitting helper</li>
<li><a
href="https://github.com/ljharb/qs/commit/e1bd2599cdff4c936ea52fb1f16f921cbe7aa88c"><code>e1bd259</code></a>
[Dev Deps] update <code>@ljharb/eslint-config</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/f4b3d39709fef6ddbd85128d1ba4c6b566c4902e"><code>f4b3d39</code></a>
[eslint] add eslint 9 optional peer dep</li>
<li><a
href="https://github.com/ljharb/qs/commit/6e94d9596ca50dffafcef40a5f64eca89962cf34"><code>6e94d95</code></a>
[Dev Deps] update <code>eslint</code>,
<code>@ljharb/eslint-config</code>, <code>npmignore</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/973dc3c51c86da9f4e30edeb4b1725158d439102"><code>973dc3c</code></a>
[actions] add workflow permissions</li>
<li>Additional commits viewable in <a
href="https://github.com/ljharb/qs/compare/v6.13.0...v6.14.1">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/openfrontio/OpenFrontIO/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-02 16:22:31 -08:00
bijx cdecdc5fa5 Feat: Add troop count bar to PlayerInfoOverlay (#2773)
## Description:

This feature adds a troop count bar into the PlayerInfoOverlay that
visualizes how many troops a player/nation has, how big of an attack
they are sending, and in general the percentages of their overall troop
count. I originally added the toggling of this feature as a setting but
thought it might be too narrow to need it's own setting. Would
appreciate anyone's thoughts on adding it back in or not.

Inspired by [this
comment](https://discord.com/channels/1359946986937258015/1359949371956789289/1452559404401430674)
in the Dev Discord.

### Video Demo


https://github.com/user-attachments/assets/4a4397f7-c0a1-475a-867d-ef00b57661c4



## Please complete the following:

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

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

bijx
2026-01-02 16:19:51 -08:00
Magnan Jules 5f4efacea2 Add Upper and Lower Silesia flags (#2771)
Resolves #2755
https://github.com/openfrontio/OpenFrontIO/issues/2755

## Description:

Add flags of Upper Silesia and Lower Silesia. Added both regions in
`resources/countries.json` and both SVG flags.

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

jeunemage333

<img width="609" height="69" alt="image"
src="https://github.com/user-attachments/assets/d223642f-f133-4e7b-a811-83a4e6b9cfe5"
/>
<img width="1910" height="980" alt="image"
src="https://github.com/user-attachments/assets/0c7b7a6c-358a-4879-9991-ef540688d790"
/>
<img width="609" height="69" alt="image"
src="https://github.com/user-attachments/assets/4b322b08-96f6-4059-a84c-cddce1eb94b7"
/>
2026-01-02 16:16:47 -08:00
FloPinguin 1eee8b4ddb New Map! "Surrounded" 🏝️ (#2770)
## 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
2026-01-02 13:09:59 -08:00
Arkadiusz Sygulski 4877e202f6 Update MIRV target selection algorithm (#2765)
## 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
2026-01-02 12:48:08 -08:00
bijx 6887ae598f Radial menu instructions updated with new Troop/Gold donation icons (#2769)
## Description:

Updates the instructions Help Menu to update the ally radial menu
screenshot to show the new gold and troop donation icons, as well as
what they do. Related to #2708

<img width="1656" height="974" alt="image"
src="https://github.com/user-attachments/assets/365e0fe5-6854-4cac-8288-039a05cf4905"
/>


## Please complete the following:

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

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

bijx
2026-01-02 20:28:12 +00:00