## Description:
Conquests are currently mixing all player types.
This is not ideal as people wonders why a 50 player game can lead to
hundred of kills.
Having separate records can also help with achievements and better
balancing.
This PR splits the conquests record into 3 categories: human, nations
and bots.
It is linked to this infra PR:
https://github.com/openfrontio/infra/pull/246
<img width="895" height="497" alt="image"
src="https://github.com/user-attachments/assets/66e49100-8114-4406-84ab-d9627355956d"
/>
While the recorded data make a distinction between bots/nations, it's
only displayed here as a single "bot" category.
## 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:
**Describe the PR.**
This PR improves how pathfinding finds a starting water tile when
launching a transport ship from a shore.
Previously, the code simply picked the first water neighbor it found.
This caused issues where, if a boat were traveling east, it might launch
out of a northern tile from a shore.
<img width="896" height="353" alt="image"
src="https://github.com/user-attachments/assets/69d83012-3397-43b3-8ab0-9ebde6ffea97"
/>
<img width="342" height="219" alt="image"
src="https://github.com/user-attachments/assets/a191f5cf-97da-4e34-a191-55ce14c794f0"
/>
The new logic checks all water neighbors and picks the "best" one by
counting how many water tiles surround it. This ensures transport ships
launch into the main body of water instead of suboptimal positions.
If two tiles have water neighbors with the same score, they are
tie-broken through a euclidean distance check.
## Please complete the following:
- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
Scisyph
---------
Co-authored-by: WilliamT-byte <williamt2023@tamu.edu>
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
## Description:
This PR resolves a crash related to rail pathfinding reported on
Discord.
```
git checkout c179249cdd
npm run dev:staging
Replay id: kEbHPSP3
```
## 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:
moleole
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
## Description:
Use `this.getEffectiveNationCount()` everywhere inside of
`LobbyPlayerView`, instead of `this.nationCount`. So the team player
counts always update properly.
## 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. In JoinPrivateLobbyModal the nation count loading was missing. That
caused the team preview UI to show different player counts compared to
the HostLobbyModal. For example it showed 0/0 nations for the
HumansVsNations team mode (instead of 2/2):
<img width="726" height="217" alt="Screenshot 2026-01-16 211337"
src="https://github.com/user-attachments/assets/8b4219de-e2b2-46ff-a600-c86915e5bdb3"
/>
2. Turn down HvN difficulty from Impossible to Hard.
We steamrolled over Hard nations in the playtest (at least in two of the
three games) because we donated lots of troops to each other.
But after some API data research I noticed that only 33% of players in
public team games ever use the donate functionality.
And we probably have less skilled players in public games than in the
playtest.
So its probably better to use the Hard difficulty to ensure balanced
gameplay.
I know, I'm overthinking this 😂
## 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:
Extracted the CopyButton into its own component, and now reusing it in
"Account" too.
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
w.o.n
## Description:
fix: performance overlay positioning
## 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
## Description:
While looking at the game rotation on my localhost page I noticed that
the cool new starting gold modifier came up veeeery rarely.
Every 33th game is just too rare, lets do "Every 20th game" 🙂
## Please complete the following:
- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
FloPinguin
Please merge it into v29, since in that version the back navigation out
of a game is currently **broken** after switching from hash-based to
path-based routing via #2740
## Description:
Protect against players accidentally leaving an active game by pressing
the browser back button. Uses the same confirmation dialog as the game
exit button.
Partially handles issue #1877 (protects against back button, not closing
tab or editing the URL directly).
<img width="861" height="373" alt="image"
src="https://github.com/user-attachments/assets/167cc137-6df3-44a7-a594-91ffd904857d"
/>
Partial credit to PR #2141
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
deshack_82603
# Pathfinding pt. 4
https://pf-pt-4.openfront.dev/
## Description:
Hello again! Pathfinding. It's fast, but inaccurate. This PR makes it
more accurate and actually faster. Sadly it is _faster_ because of a
blunder in previous PR (using BucketQueue where MinHeap would be
better), not because of a new tech. More importantly, it is more
accurate. And that's what people apparently want.
## What changed?
Most of the functional changes relate to `SpatialQuery` module. This is
the thingy that answers "we know the target, which tile of my territory
is the best to launch an invasion". To make it compute a path from South
America to the deep inland China river, it has to work on a coerced map,
one with a very small resolution, so small in fact, that every 4096 map
tiles gets compressed to just one pixel. I hope you see where this is
going.
Previously we selected a random coastal tile within this big pixel
(honestly it wasn't random at all, but could very well be for the
illustrative purposes). Now, we try to be a bit more deliberate. Since
we already know the rough location of the probably best tile, we can
exclude all other tiles from the computation. Imagine a player's
territory spans both Americas on global map - that's a lot of shores.
But since we already know the best tile is somewhere close to Miami, the
problem space was greatly reduced, no need to consider all other shores.
But pathing to the target in China from Miami is still crazy expensive.
This is where second trick comes to play - instead of pathing all the
way to China, we select a _waypoint_ in the rough direction of China,
about 100 to 200 tiles away. This way we fairly cheaply select best tile
to launch an invasion towards this abstract point. And chances are, this
point is far enough, the newly computed path is very close to being
optimal. When you throw a dart from far away, the difference between
scoring 10 and missing is very small. This is why aiming in the general
direction of the board - as opposed to the ceiling - is usually good
enough.
## Okay, but what about the crazy paths when I send invasion to the
opposed bank of a river?!
Well, pathing from America to China is cool, but most players wouldn't
notice the difference on such long paths, what about the short ones? We
now try more accurate pathing first and defer to hierarchy only if it
fails. This produces much better paths for short invasions. While the
fix described above ensures the accuracy is improved also on
medium-to-long routes.
## Playground
Yes.
https://github.com/user-attachments/assets/9cf9586f-c99a-416d-b856-8cf0a21c35ed
## CodeRabbit
Grab a 🥕. Remember `tests/pathfinding/playground` is mostly generated
code and go easy on it. It's enough for it to work and do it's job of
visualizing the paths. No need for throughout review of these files.
## 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:
moleole
## Description:
We might want to add this to v29 to have a third possible public game
modifier from the beginning on 😄 Would be fun
- Add starting gold option (0 to 1_000_000_000 allowed, also applies to
nations)
- Add gold multiplier option (0.1 to 1000 allowed, also applies to
nations and bots)
- Add third public game modifier (3% chance of starting with 5M gold)
- Why 5M? It's enough gold to massively change the game start but not
enough to insta-hydro someone (launcher + hydro is 6M)
<img width="357" height="140" alt="image"
src="https://github.com/user-attachments/assets/72acc15c-e788-4e04-8590-ac72dd9657c7"
/>
## 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
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves#2704
## Description:
Merges together easy + medium difficulties.
Before:
<img width="1500" height="580" alt="image"
src="https://github.com/user-attachments/assets/26199d52-8ef2-4feb-ae87-bbfff35e3115"
/>
After:
(dont have one to show oop)
(btw that win ratio in the first screenshot is not mine.. 💀)
## 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
## Description:
The game rank modal was still using the old style, which clashes
strongly with the new one.
This PR changes changes the modal style to be consistent with the new
one:
### Old
<img width="894" height="451" alt="image"
src="https://github.com/user-attachments/assets/c83177cf-a1ed-4ee5-9e12-7d2a9d8004cf"
/>
### New

Tagged as `v29` to have a consistent style in the same version.
## 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:
The game info panel was missing the gold generated with trains, which
was recently added into the recorded stats.
This PR adds the gold train ranking, grouped with the naval trade.
Visually the game info panel is not matching the new visual identity,
but this PR only focuses on the missing data.
<img width="898" height="482" alt="image"
src="https://github.com/user-attachments/assets/6366e5d2-23b6-40b0-b4d4-1227b5a2f811"
/>
## 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
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves#2889
## Description:
fixes login in modal:
<img width="782" height="330" alt="image"
src="https://github.com/user-attachments/assets/60f1825f-5678-4853-a78b-bbed5198b0fb"
/>
(theres also one more afterwards but that leaks my email and cba to edit
it 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:
w.o.n
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves#2868
## Description:
This PR addresses a critical memory leak in the Master server process
(causing ~30GB RAM usage).
The issue was caused by `setInterval` calling `fetchLobbies()` every
100ms. When `fetchLobbies` took longer than 100ms to complete (due to
network latency or load), requests would pile up indefinitely, creating
a massive queue of pending Promises and open sockets.
I have refactored the polling logic into a generic `startPolling`
utility (in `src/server/PollingLoop.ts`) that uses a recursive
`setTimeout` pattern. This ensures that the next `fetchLobbies` call is
only scheduled *after* the previous one has completed (successfully or
failed), preventing any request pile-up.
## Please complete the following:
- [x] I have added screenshots for all UI updates (N/A - backend only)
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file (N/A - no user facing text)
- [x] I have added relevant tests to the test directory
(`tests/PollingLoop.test.ts`)
- [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:
codimo
## Description:
The recent pathfinding rework broke the naval invasion target.
This change reverts the code to the previous working one.
<img width="232" height="273" alt="image"
src="https://github.com/user-attachments/assets/0cc3ed80-bd77-4e7b-886b-0ce5012840ac"
/>
## 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:
Bots always attacked Terra Nullius if they shared a border with Terra
Nullius.
But water is Terra Nullius...
So I changed that condition to `this.bot.neighbors().some((n) =>
!n.isPlayer())`.
## 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
Been playing this game for months, and after i feel myself enough
experienced about the game, decided to start contributing to the
project. This is my first one!
## Description:
Move indicator fx for warships. Listening MoveWarshipIntentEvent to draw
the fx. Code is basic, respectly layered and written regarding project's
structure.

## 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:
420coder
---------
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
## Description:
* Add RankedType enum, for now it's just 1v1
* Add new method to MapPlaylist to create 1v1 game config
* Update WinCheck so the last player is declared a winner on 1v1.
## 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:
Changes URL embeds within other platforms, e.g. Discord, WhatsApp & X.
Updates game URLs to `/game/<code>` instead of `/#join=<code>` (required
for embedded URLs). An added benefit of this is that you would be able
to change a url from `openfront.io/game/RQDUy8nP?replay` to
`api.openfront.io/game/RQDUy8nP?replay` (add api. In front) and be in
the right place for the API data.
Updates URLs when joining/leaving private lobbies
Appends a random string to the end of the URL when inside a private
lobby and options change - this is to force discord to update the
embedded details.
Updates URL in different game states to ?lobby / ?live and ?replay.
These do nothing other than being used as a _cache-busting_ solution.
-----------------------------------------------
### **Lobby Info**
Discord:
<img width="556" height="487" alt="image"
src="https://github.com/user-attachments/assets/efd4a06d-506c-4036-9403-ee7c9a669e21"
/>
WhatsApp:
<img width="353" height="339" alt="image"
src="https://github.com/user-attachments/assets/3b2d0c69-988c-424f-9dee-f4e6a6868f6b"
/>
x.com:
<img width="588" height="325" alt="image"
src="https://github.com/user-attachments/assets/d9e78169-20be-4a3e-8df4-8ad41d08a750"
/>
-------------------------
### **Game Win Details**
Discord:
<img width="506" height="468" alt="image"
src="https://github.com/user-attachments/assets/69947774-c943-4a50-b470-5634ed3bf3d7"
/>
WhatsApp:
<img width="770" height="132" alt="image"
src="https://github.com/user-attachments/assets/eec28bf8-bf64-4ab8-954e-03dfdd1aae40"
/>
x.com
<img width="584" height="350" alt="image"
src="https://github.com/user-attachments/assets/168063e2-b707-422b-b7a1-0025f3ebeb92"
/>
## 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
## Description:
The current gold stats don’t include gold generated by trains, even
though this is a significant part of the economy for many players.
This PR tracks those stats with two values:
- other players trains visits the player station
- the player trains visits any station
Linked to this infra PR: https://github.com/openfrontio/infra/pull/242
## 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:
Should fix the broken 1v1 on staging. The issue was that we had multiple
staging environments, and the matchmaker would often route a player to a
game on a different staging server, so the client couldn't find the
game.
So now each deployment has a unique id, and the matchmaker only connects
players & servers that have the same instance id.
## 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
# Pathfinding pt. 3
## Description:
This PR introduces final change to the pathfinding - path refinement. It
optimizes Line of Sight refinement by searching with for the best tile
with a binary search instead of linearly. And then spends the recovered
budget on better refinement of the first and last 50 tiles of the
journey - the place where user is most likely to look at. Additionally
this PR re-introduces magnitude check and makes the ships prefer sailing
close to the coast, but not too close.
## 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
## What?
| Before | After |
| :--- | :--- |
| <img width="1097" height="1117" alt="image"
src="https://github.com/user-attachments/assets/4a0b300d-10ef-4151-b6dc-33acfb49f992"
/> | <img width="1093" height="1119" alt="image"
src="https://github.com/user-attachments/assets/cf81c515-c145-40f4-91e5-a4353986907b"
/> |
| <img width="1096" height="1129" alt="image"
src="https://github.com/user-attachments/assets/21b46bce-f961-4259-88f6-fe4a66180270"
/> | <img width="1098" height="1126" alt="image"
src="https://github.com/user-attachments/assets/d92587d1-e6b6-4353-b4a4-1efe71bca43d"
/> |
## Performance
There is actually a severe performance impact of these changes. The path
initial path takes almost 2x as long to generate - this is because pre
processing can only do so much if the initial path is ugly. Luckily in
real gameplay we only need to do this calculation once per edge, so the
actual observed performance impact should be much smaller. Cache FTW.
| | No Cache | Cache |
| :--- | :--- | :--- |
| Before | 277.04ms | 208.58ms |
| After | 498.34ms | 264.27ms |
## DebugSpan
Small utility, it allows any code to be easily instrumented for
performance. The idea is the same as with [OTEL
Spans](https://opentelemetry.io/docs/concepts/signals/traces/). Produce
a span, create sub-spans, measure whatever you need. Works only when
`globalThis.__DEBUG_SPAN_ENABLED__ === true`, otherwise no-op.
Cool stuff, try it out:
```ts
// Convenient wrapper, small performance impact
return DebugSpan.wrap('add', () => a + b)
// Synchronous API, basically free
DebugSpan.start('work')
work()
DebugSpan.end()
// Create sub spans
DebugSpan.wrap('complex', () => {
const aPlusB = DebugSpan.wrap('add', () => a + b)
DebugSpan.set('additionResult', () => aPlusB) // Store data
return aPlusB * c
})
// Access spans, data and timing
const span = DebugSpan.getLast()
const compelxSpan = DebugSpan.getLast('complex')
console.log(complexSpan.duration, complexSpan.data['additionResult'])
```
These are virtually free and can be enabled on-demand **in production**
and available in the devtools. Under the hood devtools integration is
just a wrapper around [Performance
API](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API).
For clarity data keys not prefixed by `$` are omitted from the
integration. Every key prefixed with `$` must be fully JSON
serializable.
<img width="977" height="799" alt="image"
src="https://github.com/user-attachments/assets/b4d43506-1639-4f78-a611-30e61de12a07"
/>
## Description:
Doesn't need a description :D
https://github.com/user-attachments/assets/8de576fd-050b-4b35-8526-e4c88d1a9f25https://github.com/user-attachments/assets/c99147a1-efdf-426b-96d1-e996e01f89aa
## 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:
fix(ui): add missing dark variant to styles.css
Before:
<img width="549" height="77" alt="image"
src="https://github.com/user-attachments/assets/d7c2bf92-691b-473c-880a-da678eb792a3"
/>
After:
<img width="555" height="84" alt="image"
src="https://github.com/user-attachments/assets/a2c828db-7fea-409a-abdd-fefc0dc237f0"
/>
## Please complete the following:
- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
wraith4081
---------
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
## Description:
This PR makes several existing keybinds configurable that were
previously fixed and could not be changed in the keybind settings.
This is one of the required PRs to fully remove all keybind explanations
from the HelpModal.
This work is based on the following feedback by @ryanbarlow97:
> "This probably needs to be redone / removed from help, and just have a
section saying how to get to the keybinds modal inside settings"
>
https://github.com/openfrontio/OpenFrontIO/pull/2872#issuecomment-3740006017
Some keybinds described in the HelpModal already existed internally, but
users had no way to change them.
By making these keybinds configurable, we can now safely replace those
explanations with a simple reference to the keybind settings instead.
This helps:
- Remove keybind explanations from the HelpModal
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
aotumuri
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
## Description:
The calculation is based on: 50 players per 1_000_000 land tiles,
limited at 125 players because of performance
Second number is 75% of that, third one 50%
That way, the player counts are staying mostly the same
Look at the "Dynamic Config" column, these are the new player counts:
(The 125 players limit is missing in that column, only relevant for the
twolakes map)
<img width="930" height="1033" alt="Screenshot_2026-01-12_152758"
src="https://github.com/user-attachments/assets/e1791740-e263-47b3-8b27-4f9aa358d381"
/>
<img width="926" height="324" alt="Screenshot_2026-01-12_152814"
src="https://github.com/user-attachments/assets/78d6789b-374f-4f8b-b50f-f6f08395572b"
/>
This PR also removes `MapDescription` from `Maps.ts` because its unused.
And this PR updates the map-generator `README.md` to reflect the changes
## 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
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #(issue number)
## Description:
Moved the Modal Headers into its own class
## 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
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #(issue number)
## Description:
Remove borders from some elements
**Tailwind changes only**
## 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
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #(issue number)
## Description:
remove the colours from the shop modal, also small tweak to header bar
in instructions
**Only Tailwind Changes**
<img width="843" height="209" alt="image"
src="https://github.com/user-attachments/assets/1f99aa8d-8756-4b70-9ff0-6495d5eb48bf"
/>
<img width="841" height="183" alt="image"
src="https://github.com/user-attachments/assets/ac40ed0d-7588-4336-b3d1-ce4be5f8a312"
/>
## 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
## Description:
fix url
## 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
## Playtest
https://pf-pt-2.openfront.dev/
## Pathfinding Refactor pt. 2
<img width="1536" height="1024" alt="image"
src="https://github.com/user-attachments/assets/9477958e-54b7-4c83-b317-ba789e809e9e"
/>
This is a follow-up to a previous PR introducing pathfinding changes.
This time, it introduces a complete refactor of `pathfinding` directory
and breakdown into composable pieces.
### Unified PathFinder interface
`PathFinder<T>` and `SteppingPathFinder<T>` are introduced to unify
**all** pathfinding across the application. First one exposes complete
path, while stepping variant allows the callee to iterate over the path
by calling `.next`. All pathfinders share this one common interface,
which makes them easy to use in any scenario -
`PathFinding.Water(game).search(from, to)`.
`SteppingPathFinder<T>` extends `PathFinder<T>` with an ability to
iterate over the path. It handles caching, storing current index and
invalidation. This allows the units to not care about the inner workings
of the pathfinder and just call `pf.next(current, target)` and receive
instructions on what to do next.
### Common entry point
All pathfinders are now exposed from common `PathFinding` entrypoint:
- `PathFinding.Water`
- `PathFinding.Rail`
- `PathFinding.Stations`
- `PathFinding.Rail`
Additional entry point is introduced for pathfinders which need to work
both in the worker, but also on the frontend, which lacks `Game`
interface. Currently only `UniversalPathFinding.Parabola` is available.
### Spatial Query
New module has been introduced close to `pathfinding` - `SpatialQuery`.
It aims to resolve any questions game may have about finding tiles
meeting criteria. Currently `SpatialQuery.closestShore(player, target)`
and `SpatialQuery.closestShoreByWater(player, target)` are available -
they help answering questions about naval invasion: "What is the best
landing location from user's click?" and "Which our tile should be used
to launch the transport ship?". Under the hood they use very similar
mechanics to pathfinding, so it felt right to put them close by.
### Modular architecture
Pathfinders now support transformers: `MiniMapTransformer`,
`ShoreCoercingTransformer`, `ComponentCheckTransformer`,
`SmoothingTransformer`. Transformers functions like a middleware in the
pathfinding chain. They wrap around the pathfinder and provide
additional functionality. This allows the pathfinder to focus on
actually finding the path instead of doing unrelated things.
Example chain for simple (A*) water pathfinding:
```ts
static WaterSimple(game: Game): SteppingPathFinder<TileRef> {
const miniMap = game.miniMap();
const pf = new AStarWater(miniMap);
return PathFinderBuilder.create(pf)
.wrap((pf) => new ShoreCoercingTransformer(pf, miniMap))
.wrap((pf) => new MiniMapTransformer(pf, game.map(), miniMap))
.buildWithStepper(tileStepperConfig(game));
}
```
The Pathfinder - here `AStarWater` - does not care about the conversion
between minimap and main map tiles. It also does not care if the source
or destination is a land tile. The transformers take care of that. The
pathfinder gets a set of valid coordinates and produces the path -
that's it.
Modular approach makes working on a particular set of utilities much
easier - for example map upscaling is handled consistently across all
pathfinders. Additionally, the pathfinders are not tied to the
particular map resolution used. Pass them a different map and they will
work the same.
### Algorithms
Algorithms used are neatly organized inside
`src/core/pathfinding/algorithms`. They are prefixed with the algorithm
name and suffixed with the use case. File without suffix exposes generic
version ready to traverse any graph with adapters. Specialized versions
either use an adapter or inline logic when performance is critical -
using adapters leads to 20-30% performance loss.
The directory includes `A*` and `BFS` but also other useful utils, such
as `AbstractGraph` used to generate... an abstract graph on top of the
tile map and `ConnectedComponents` helping to identify whether two tiles
are connected by a path without actually computing the path.
### Playground
The playground have been updated with new algorithms, including tweaked
very greedy `A*`.
<img width="2175" height="1424" alt="image"
src="https://github.com/user-attachments/assets/1f833651-0024-4299-bf86-882f5368358c"
/>
### Tests
Yeah, there are some, a little too many if I say so myself. But there
are no useless tests. I had to ensure refactored code works somehow
reliably. This PR comes with trust me bro guarantee, but I would
appreciate someone confirming **naval invasions, nukes (esp. MIRV) and
warships**.
### Discord
`moleole`
GL & HF
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves
https://discord.com/channels/1330359017247346812/1330365278420471911/1358027146139795486
## Description:
In HelpModal, only the TargetIcon was displayed in red, which was
inconsistent with the other icons.
This PR updates its color to white so it matches the rest of the icons.
before
<img width="397" height="458" alt="スクリーンショット 2026-01-11 22 24 54"
src="https://github.com/user-attachments/assets/2a2f5aa0-a31c-4ecb-887e-f151689c3236"
/>
after
<img width="370" height="438" alt="スクリーンショット 2026-01-11 22 25 08"
src="https://github.com/user-attachments/assets/d0c74805-8bc8-4e94-8a18-23488aba0389"
/>
## 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: FloPinguin <25036848+FloPinguin@users.noreply.github.com>
## Description:
UI Refinements requested by @evanpelle check https://ui.openfront.dev
## 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
Resolves
https://discord.com/channels/1359946986937258015/1458658371891761339/1459478370977972316
## Description:
The play-like icon on the left side of the Recent Games UI looked
clickable but did not actually start a replay, which could be
misleading.
This PR updates the behavior so that clicking the icon now starts the
replay, matching the visual affordance and reducing user confusion.
https://github.com/user-attachments/assets/db9f02d9-9492-47ba-948b-6a6e0166d4d3
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
aotumuri
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves#1225
## Description:
Replace all raw displayMessage strings with events_display.* keys +
params and add the new English translations in resources/
lang/en.json so EventsDisplay can translate them.
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
aotumuri
---------
Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Description:
Fixed a bug that prevented debug mode from working.
Made it so that parameters are displayed.
<img width="800" height="559" alt="スクリーンショット 2026-01-10 14 24 51"
src="https://github.com/user-attachments/assets/2eff3073-15fe-4879-9448-c7f20b5e4eab"
/>
translation-key::parameters
## 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
## Description:
Didier map name had a little UI problem.
And unrelated change: Because Lewis today said "it should be super low"
I turned down the frequency of this map from 2 to 1.
Previous:
<img width="1916" height="1312" alt="image2"
src="https://github.com/user-attachments/assets/0a84160b-91a8-4d02-b707-fa9eea1a15fd"
/>
Fixed:
<img width="562" height="476" alt="image"
src="https://github.com/user-attachments/assets/31fed7b5-c128-45cd-a63d-0aab3345cea3"
/>
## 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:
In HelpModal, only the BoatIcon was displayed in black, which was
inconsistent with the other icons.
This PR updates its color to white so it matches the rest of the icons.
before
<img width="619" height="235" alt="スクリーンショット 2026-01-10 14 33 44"
src="https://github.com/user-attachments/assets/41c10308-7701-40bf-b068-9e14eb78a83a"
/>
after
<img width="722" height="260" alt="スクリーンショット 2026-01-10 14 35 17"
src="https://github.com/user-attachments/assets/2d535ded-83d2-4f3d-990d-49aaa1230642"
/>
## 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
Resolves#2652#2291
## Description:
Resolves a regression after a new design changes where keybinds
explicitly set to "Null" were incorrectly reverted to default values
instead of remaining unbound.
Updates the input handler to preserve "Null" as the designated value for
an unbound key. The UI now reflects this by displaying "None" for
keybinds that are set to "Null", providing clear user feedback.
Before/After:
<img width="378" height="371" alt="image"
src="https://github.com/user-attachments/assets/d1d640f2-93aa-47f1-be8e-7d8c68183aa1"
/> <img width="379" height="370" alt="image"
src="https://github.com/user-attachments/assets/f0512cce-c6e9-4180-9517-7669aed76f6f"
/>
## 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:
webdev.js
Co-authored-by: antigrid <Stepan.Hembarovskyi@Inu.edu.ua>