cancelNukesBetweenAlliedPlayers previously only cancelled a nuke if its exact target tile was owned by the new ally. This meant nukes aimed at neutral or own tiles near allied territory would survive alliance formation and still land (and break the alliance).
Now uses wouldNukeBreakAlliance — the same blast-radius logic used by maybeBreakAlliances on impact — so a nuke is cancelled if its blast would have meaningfully hit the ally's tiles or structures. Also switches from the exhaustive listNukeBreakAlliance (scans all players) to wouldNukeBreakAlliance with a single-player allySmallIds set for early-exit performance.
## Description:
When multiple nukes detonated in the same tick, clearTrail was called
once per dying unit. Each call scanned all remaining units to repaint
overlapping trail tiles — O(dead × alive × trail_len) per tick.
Replace with a deferred batch: dying units are queued into
pendingTrailClears during drawUnitsCells, then flushTrailClears()
processes them all at once after the draw pass. All trail tiles are
cleared in a single loop (skipping duplicates), followed by one repaint
scan of surviving units — O((dead + alive) × trail_len).
Also fixes a minor bug in the original: the surviving unit's
relationship is now used when repainting its trail (previously the dying
unit's relationship was used, which gave wrong colors in alternate-view
mode).
## 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:
The warship pathfinder operates on a 2x downscaled mini-map, and
upscaling mini-map paths back to full coordinates produces diagonal
interpolated steps. At close range (< 20 tiles), the entire path
consists of these diagonal moves, causing the warship to approach the
trade ship at an awkward angle and never converge cleanly.
## 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:
Updating TypeScript to 6.0.3.
Updating TypeScript-eslint to 8.59.1 for TS6 support.
Concurrently needed to get updated as well to remove deprecated warning.
Most things deleted are now just defaults.
## 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:
Babyboucher
Part of [#2661](https://github.com/openfrontio/OpenFrontIO/issues/2661)
(split into 3 PRs so they are not too large..)
## Description:
Part 3/3 of
[#2661](https://github.com/openfrontio/OpenFrontIO/issues/2661).
This PR adds the retreat control and override behavior for warships:
- Manual override: moving a warship manually cancels retreat and
suppresses auto-retreat for 5 seconds
- Aggro override: a retreating warship will aggro a nearby enemy
transport or warship before continuing retreat
- Heal-at-port command for sending a warship to a friendly port manually
- Friendly-port validation for HealAtPortExecution
- Regression tests for manual override, aggro override, and heal-at-port
behavior
## 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:
zixer._
---------
Co-authored-by: iamlewis <lewismmmm@gmail.com>
Co-authored-by: evanpelle <evanpelle@gmail.com>
## Description:
Version identifier within MLS: v5.3
[Changed languages]
- fr
- ru
- uk
[Change volume]
- Changed languages: 3
- Changed files: 3
- Changed lines: 6165
- metadata.json: unchanged
Final reviewer: meow02952
This PR was generated by the PR sender tool, then checked and submitted
by the final reviewer.
## 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:
Some new players were having trouble finding themselves on game start
* Emits a GoToPlayerEvent (zoom=8) on the first turn after the spawn
phase, using a hasGoneToPlayer flag to ensure it only fires once per
session
* Adds a zoom parameter to GoToPlayerEvent so callers can specify a
target zoom level
* Adds smooth zoom animation to TransformHandler — the camera now eases
to the target scale alongside the existing position easing, with
screen-center correction to avoid visual jumping on mobile (where canvas
and map dimensions differ)
* Moves GoToPlayerEvent, GoToPositionEvent, and GoToUnitEvent out of
Leaderboard.ts into TransformHandler.ts, where they logically belong
## 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:
StructureIconsLayer and StructureDrawingUtils fixes and improvements.
Most notably have it restore structure icons after webGL context loss.
Inspired by @Skigim's
https://github.com/openfrontio/OpenFrontIO/pull/3339,
https://github.com/openfrontio/OpenFrontIO/pull/3480. Fixes his
https://github.com/openfrontio/OpenFrontIO/issues/3207, contains only
those fixes from the Issue that are actually valid and needed fixes, on
top of his earlier merged PR.
### CONTAINS (partly written by AI, excuse the exaggerated language)
**1.**
* ** AutoDetectRenderer: ** now, if Hardware Acceleration is unavailable
or disabled, Structure Icons will be displayed using Canvas renderer.
Otherwise it will use either WebGL or WebGPU, depeding on which is
available. PixiJS currently prefers WebGL but it will switch this to
WebGPU at one point. We can also force it to WebGPU as explained in the
comment.
* ** Canvas: ** on Canvas, what doesn't work is gracefully skipped. The
non-working parts will be fixed, see this issue in their repo, but until
then it will work fine for us anyway:
https://github.com/pixijs/pixijs/issues/11981
* **WebGPU Context Loss:** PixiJS doesn't restore this context itself.
Instead we do it by calling setupRenderer again on device loss.
* **WebGL Context Loss:** To know when we need to restore the layer,
don't use native event (`webglcontextrestored`) but use PixiJS's
internal hook (`this.renderer.runners.contextChange`). This prevents our
cache-clearing commands from interrupting Pixi while it's still busy
rebuilding its internal GL State Machine buffer. With links severed, we
need to clear and rebuild all icons to restore them.
* **WebGL Context existance Check (`this.renderer.context?.isLost`):**
This prevents a crash in PixiJS. Fixes black map background and all
graphics frozen, which has been reported a few times. Issue created in
their repo: https://github.com/pixijs/pixijs/issues/12032.
* **Redraw:** for Canvas context restore or on Alt-R, a call from
GameRenderer now actually restores icons. Also called for WebGPU device
loss and after contextChange WebGL restoration. Checks for WebGL
context.isLost so a calls from Alt-R etc won't meddle while GL context
is lost.
* **Orphaned Object Leaks:** In PixiJS v8, `Container.destroy()` does
*not* recursively destroy its children. This PR explicitly adds
`.destroy({ children: true })` inside icon deletion states. This stops
thousands of `PIXI.Sprite` and `PIXI.BitmapText` child nodes from
leaking and choking Pixi when it attempts a WebGL restore.
* **Texture Lifecycle:** Invalidate caching logic in `SpriteFactory` now
correctly executes `.destroy(true)` on `PIXI.Texture` objects.
Previously, they were only deleted from the textureCache Map, retaining
a phantom grip on GPU memory buffers.
* **Don't remove PIXI.Texture.EMPTY from textureCache: `createTexture()`
in `SpriteFactory` stores `PIXI.Texture.EMPTY` (a singleton) in
`textureCache` when a structure type has no known shape. When not
preventing removal of the EMPTY texture, `clearCache()` would call
`texture.destroy(true)` on PixiJS's shared global empty texture,
breaking all sprites in the renderer that fall back to it.
**2. Small Memory/Perf Optimizations**
* **The Shared 2D Canvas Optimization:** To prevent allocating endless
tiny `<canvas>` elements every time a structure color is loaded,
`SpriteFactory` now utilizes a cleanly shared `colorCanvas` singleton.
To keep this safe from hardware acceleration crashes (where the 2D
context dies alongside WebGL), it accurately nullifies itself in
`clearCache()` and lazily instantiates on the next call
(`getImageColored()`).
* **Bypassing Inefficient Textures Cache:** Now passing the `skipCache:
true` argument implicitly to dynamic UI elements via
`PIXI.Texture.from(structureCanvas, true)`.
* **Zero-Allocation Filters (No more GC Stutters):** `renderGhost()`
previously spawned numerous `new OutlineFilter(...)` WebGL shaders when
hovering over invalid tiles, compounding to many leaked Shader Programs.
We hoisted these filters to static class properties initialized once,
and went a step further: hoisted the wrapping Array structures too
(`filterRedArray`, `filterGreenArray`). This eliminates many pointless
micro-allocations and GC sweeps entirely.
**BEFORE, for webGL:**
https://youtu.be/durJxNFNePs
**AFTER, for WebGL:**
https://youtu.be/VnYEFMx4gfM
**AFTER, for Canvas:**
https://youtu.be/zT720oKxcaI
**AFTER, for WebGPU:**
https://youtu.be/J09Wee2qTs8
The performance optimizations weren't well measurable in my tests but
there's no downgrade at least. WebGPU should bee better than WebGL when
we would force it but again, currently PixiJS prefers WebGL hardcoded so
only if we disallow WebGL will it use WebGPU if it is available,
otherwise fallback gracefully to Canvas still.
Canvas skips parts gracefully, as long as the non-breaking issue exists
in PixiJS (as explained above):
<img width="952" height="705" alt="AFTER Canvas in Firefox skips
non-supported gracefully"
src="https://github.com/user-attachments/assets/17e8d8ab-05dc-47cb-ab11-f0f4d015a42a"
/>
## 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:
tryout33
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
## Description:
The README referenced `resources/images/OpenFrontLogo.svg` and
`resources/images/OpenFrontLogoDark.svg`, but those files do not exist
at that path. The actual logo SVGs live under `proprietary/images/`.
Updated all three `<picture>` element references to point to the correct
directory so the logo renders properly on GitHub.
## 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:
ArchipelagoSea is a very "special" map with the extreme amount of tiny
islands, and the map maker said "could there be a way to make
Archipelago Sea have 5M or 25M starters more often? I feel like the map
is too unorthodox to be played in normal settings"
So lets restrict it to the special rotation, like arcade maps. People
expect crazy-stupid games there.
## Please complete the following:
- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
FloPinguin
## Description:
<img width="276" height="178" alt="Screenshot 2026-04-29 at 4 18 23 PM"
src="https://github.com/user-attachments/assets/ed2d0416-00c2-4d55-8ee1-d7804b6276ab"
/>
## 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
updates wording to "Public Player ID"
## Description:
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:
w.o.n
## Description:
Replaces the HTTP POST /api/start_game/:id endpoint with a WebSocket
intent, making private game start consistent with how kick_player and
update_game_config already work. Also verifies that only the lobby
creator can start a game.
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
evan
## Description:
Nations preform poorly on large water maps, these changes aims to
improve how they handle and react to water combat.
Adding the ability for hard and impossible nations to retaliate against
incoming transport ships.
Adding the ability for ships to be moved if the nation is not able to
build a new ship.
## 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:
babyboucher
---------
Co-authored-by: iamlewis <lewismmmm@gmail.com>
Co-authored-by: FloPinguin <25036848+FloPinguin@users.noreply.github.com>
## Description:
Change inspired by Territorial.io . Renames the Mediterranean sea map to
Mare Nostrum, the ancient name of the sea given by the Romans. The NPCs
of the map are already roman provinces, so this change is more thematic
and also adds a creative name like "Gateway to the Atlantic" and
"Between Two Seas"
## 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:
tri.star1011
## Description:
Cross-origin CSS-mask icons were failing on Chrome and Safari because
mask: url(...) triggers a CORS-mode fetch (unlike plain <img>), and
stale browser caches without ACAO break per-user. Instead change the
svgs with the appropriate colors so we don't need to mask 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:
evan
## Description:
In this example, the two nations DONT see each other as neighbors, but
as ISLANDERS. Because they dont have a direct border connection, there
is water in between.
<img width="526" height="329" alt="image"
src="https://github.com/user-attachments/assets/cf2c15b5-7793-4445-afd2-920d6cd50a2a"
/>
This is a big problem, because most of the logic in AiAttackBehavior
gets ignored. Only the "islander" strategy runs (late, because its a
not-important strat).
### Summary
- `PlayerImpl.neighbors()` now includes cross-water neighbors: a new
`shoreReachableNeighbors()` helper samples every 10th shore border tile
and looks up to 5 tiles in each cardinal direction across water, finding
land owners on the other side (covers rivers up to 4 tiles wide).
- `AiAttackBehavior.maybeAttack()` extends the `hasNonNukedTerraNullius`
check to also trigger on TN detected via `player.neighbors()`, so
nations notice and pursue TN that is only reachable across a river.
- `sendAttack()` uses a new `hasLandBorderWithTerraNullius()` land-only
adjacency check to decide between a land attack and a boat attack for
TN, rather than `sharesBorderWith()` which includes water tiles.
- Added `sendBoatAttackToNearbyTerraNullius()`: when no TN land is
directly adjacent, the AI scans its shore border tiles for unowned land
across water and dispatches a transport ship.
### Also works for Tribes!
Tribes can boat rivers now, really cool.
https://github.com/user-attachments/assets/382e85aa-c437-4e0c-afc2-0c381432da3d
## 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:
- Nations on Easy no longer betray human allies
- Nations on Easy now attack humans only 25% of the time (down from 50%)
- Increased Easy reaction tick range (65-100, up from 65-80) so nations
respond more slowly
- Raised MIRV steamroll-stop thresholds on Easy (city gap multiplier 1.5
-> 2, min leader cities 15 -> 20) and slightly tuned Medium/Hard
thresholds
## 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
Resolves#3755
## Description:
The game ID in the history details panel was displayed as plain
unselectable text, making it difficult to copy.
Replaced the static text div with the existing <copy-button>
component in compact mode, which allows users to click the game ID
to copy it to clipboard instantly.
No screenshot provided — feature requires a logged-in account to access
game history. The change replaces a static text div with the existing
<copy-button compact> component on line 118 of GameList.ts.
## 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
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Description:
StructureLayer.loadIcon and StructureDrawingUtils.loadIcon hand-roll new
Image() and feed the result into a canvas. With assets now served from a
cross-origin CDN, the default no-cors fetch tainted the canvas, and
WebGL's texImage2D rejected the upload `Uncaught SecurityError: Tainted
canvases may not be loaded`. Setting crossOrigin = "anonymous" before
src switches to a CORS-checked fetch (R2 already returns ACAO), so the
canvas stays clean and the texture upload succeeds.
Other new Image() and <img> sites in the codebase don't need the change
— they're either DOM-only or read naturalWidth/naturalHeight 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:
evan
## Description:
Add Map - Los Angeles (With Roads)
Whats NY without LA? What is LA without its roads? Here is a larger map
where I have turned LAs road network into rivers. Nations named to areas
of the city or surrounding area. Map geo data is from OpenTopography. I
stenciled the highways from screenshots of online maps and some artistic
choice.
https://discord.com/channels/1284581928254701718/1482605671697613081/1482605671697613081https://www.youtube.com/watch?v=6td9wiQKE9s
## 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
##Discord username
PlaysBadly
---------
Co-authored-by: evanpelle <evanpelle@gmail.com>
## Description:
The motivation behind this PR is to standardize colors & icons for
incoming and outgoing attacks. Outgoing attacks are always aquarious and
incoming are red. This also makes it much easier to see which attacks
are incoming vs outgoing at a glance, as previously the color changed
depending on attack effictiveness. Instead, show a small bar on the left
side that displays attack effectiveness.
<img width="498" height="456" alt="Screenshot 2026-04-27 at 12 58 53 PM"
src="https://github.com/user-attachments/assets/ea6928b3-5dfa-47fa-84d2-63e1e81ef6a4"
/>
Updates the in-game attack labels to match AttacksDisplay: a single
soldier icon recolored via CSS filters, aquarius for outgoing and
red-400 for incoming. Color is now purely directional — the previous
attacker-vs-defender comparison (and the troopAttackColor /
troopDefenceColor helpers that drove it) is gone, along with the
defenderTroops plumbing.
Also adds zoom-aware sizing via a new computeLabelScale(zoom) (full
screen size when zoomed in, linear shrink with a floor so labels never
disappear), bumps font/padding/snap-jump threshold for readability, and
moves immutable per-label DOM writes (icon src/filter, color) into
element creation so the per-tick path only updates the troop count.
Also fixes a bug where the labels kept swapping when 2 clusters where
similar size
## 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:
Add an optional CDN_BASE env var that prefixes hashed asset URLs from
asset-manifest.json, so the app can serve static assets from R2/CDN
instead of the app origin. The value is determined at runtime via the
EJS template (window.CDN_BASE) — empty string means "same origin,"
matching today's behavior.
A hack to load the worker bundle:
A same-origin Blob script that dynamic-import()s the cross-origin worker
module and buffers early postMessage calls until the imported module's
handler attaches, sidestepping the browser's refusal to construct a
Worker directly from a cross-origin 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:
evan
Resolves#3590
## Description:
The spawnHighlight() function in TerritoryLayer.ts was using `=== 0`
as the condition to return early, which caused the spawn highlight to
render on 4 out of every 5 frames instead of the intended 1 out of 5.
Changed `=== 0` to `!== 0` so the function skips rendering on 4/5
frames, improving performance especially on large maps.
## 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
- [x ] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Description:
`deleteAllStructures` did not check for `isMarkedForDeletion`, not very
clean. Now its clean.
Also rename to `deleteNextStructure` because its not possible to delete
more than 1 structure at a time.
## 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:
- Hard / Impossible nations in team games auto-stop trading with all
enemies
- If there are a LOT of nations on the map (Enzo stream with 400 nation
HvN private games) they no longer start with a city, they start with eco
(port / factory) because they cannot gain much gold from bot-killing
- Impossible nations built way too many missile silos sometimes, caused
by the SAM overwhelming logic. Fixed now.
- In public HvN games with 5M starting gold, nations placed their
structures way too fast, which slowed down their expansion. And humans
could easily cause a lot of damage with one atom bomb. Now their first
structure is a SAM (on hard / impossible) and they wait between their
earlygame structure placements.
- Nations now spread out their port placements more evenly
- Nations are now able to attack much stronger enemies in team games
(They can expect donations)
- Improve performance a bit by adding more early-returns (Dont run any
nuking logic if nukes are disabled, no alliance logic if alliances are
disabled, no boating logic if transport boats are disabled, ...)
- Fix some of the "cannot send troops" messages in the console
(DonateTroopExecution)
- Nations build their first missile silo sooner, they should also build
more SAMs
- Nations spend their gold better after reaching the save-up-target
(previously they stopped nuking)
- Optimized save-up-targets for team games
- The richest impossible nation is nuking very dense players now (lot of
structure levels on a small island)
### How does a 5M gold HvN start look like now?
https://github.com/user-attachments/assets/e9da89c3-c0d4-4144-a741-3101746b16da
## 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
Part of [#2661](https://github.com/openfrontio/OpenFrontIO/issues/2661)
(split into 3 PRs so they are not too large..)
## Description:
Part 2/3 of
[#2661](https://github.com/openfrontio/OpenFrontIO/issues/2661).
This PR adds port-based healing and docking behavior:
- Passive healing near friendly ports
- Active docked healing pool scaled by port level and shared across
docked ships
- Docking radius and capacity-by-port-level behavior
- Waiting behavior near full ports until a slot opens
- Auto-undock once fully healed
For the active healing, it works like `ActiveHeal = (PortLevel * 5) /
DockedShipsAtThatPort`
Ex:
1 ship at level 1 port -> +5 HP/tick
1 ship at level 2 port → +10 HP/tick
2 ships at level 3 port → +7.5 HP/tick each
Includes regression tests covering healing math and docking/waiting
behavior.
## 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:
zixer._
## Description:
Small server-side data handling adjustment with focused archive
coverage.
## 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
Please put your Discord username so you can be contacted if a bug or
regression is found:
apick
## Description:
## Summary
Include Vite's bundle output (`vendor-*`, `index-*`, workers, CSS under
`static/assets/`) in the asset manifest so the R2 deploy upload covers
them alongside hashed source assets. Move the manifest from
`static/_assets/asset-manifest.json` to `static/asset-manifest.json`
since it now describes both trees, and update `update.sh` to extract the
whole `static/` tree.
## 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:
It first sends the manifest to the worker to get a list of missing
files, then for each missing file it uploads them to r2 via cf worker.
This PR also has us write out the manifest in plan json instead of an
mjs file. This makes it easier for the shell script to parse
## 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
- [ ] 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:
Adds map of the Baja California peninsula in Mexico. Majority of this
map is brown terrain to simulate the (Sonora) desert
Mexican and American states as NPCs. The peninsula while having little
landmass is balanced by the fact it will be very easy to pirate from it
<img width="503" height="583" alt="Captura de pantalla 2026-04-18
151337"
src="https://github.com/user-attachments/assets/b1acd93a-fbe4-4d17-95b6-5f4c86ec872f"
/>
Relief data from OpenTopography, already credited
## 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:
tri.star1011
## Description:
We have brand colors:
<img width="738" height="900" alt="Screenshot 2026-04-25 at 12 52 29 PM"
src="https://github.com/user-attachments/assets/aac69e87-91f2-4c3f-9f1e-f69f48f5943e"
/>
So update the homepage & in-game UI to use those colors:
<img width="1185" height="946" alt="Screenshot 2026-04-25 at 12 51
06 PM"
src="https://github.com/user-attachments/assets/89a0b12c-2db1-43d4-9500-fcf405c0f7ff"
/>
Also updated buttons to use the o-button element
## 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
Bumps the npm_and_yarn group with 2 updates in the / directory:
[fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser)
and [postcss](https://github.com/postcss/postcss).
Updates `fast-xml-parser` from 5.5.8 to 5.7.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/releases">fast-xml-parser's
releases</a>.</em></p>
<blockquote>
<h2>upgrade <code>@nodable/entities</code> and FXB</h2>
<ul>
<li>Use <code>@nodable/entities</code> v2.1.0
<ul>
<li>breaking changes
<ul>
<li>single entity scan. You're not allowed to use entity value to form
another entity name.</li>
<li>you cant add numeric external entity</li>
<li>entity error message when expantion limit is crossed might
change</li>
</ul>
</li>
<li>typings are updated for new options related to process entity</li>
<li>please follow documentation of <code>@nodable/entities</code> for
more detail.</li>
<li>performance
<ul>
<li>if processEntities is false, then there should not be impact on
performance.</li>
<li>if processEntities is true, but you dont pass entity decoder
separately then performance may degrade by approx 8-10%</li>
<li>if processEntities is true, and you pass entity decoder separately
<ul>
<li>if no entity then performance should be same as before</li>
<li>if there are entities then performance should be increased from past
versions</li>
</ul>
</li>
</ul>
</li>
<li>ignoreAttributes is not required to be set to set xml version for
NCR entity value</li>
</ul>
</li>
<li>update 'fast-xml-builder' to sanitize malicious CDATA and comment's
content</li>
</ul>
<h2>use <code>@nodable/entities</code> to replace entities</h2>
<ul>
<li>No API change</li>
<li>No change in performance for basic usage</li>
<li>No typing change</li>
<li>No config change</li>
<li>new dependency</li>
<li>breaking: error messages for entities might have been changed.</li>
<li></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.12...v5.6.0">https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.12...v5.6.0</a></p>
<h2>performance improvment, increase entity expansion default limit</h2>
<ul>
<li>increase default entity explansion limit as many projects demand for
that</li>
</ul>
<pre><code>maxEntitySize: 10000,
maxExpansionDepth: 10000,
maxTotalExpansions: Infinity,
maxExpandedLength: 100000,
maxEntityCount: 1000,
</code></pre>
<ul>
<li>performance improvement
<ul>
<li>reduce calls to toString</li>
<li>early return when entities are not present</li>
<li>prepare rawAttrsForMatcher only if user sets <code>jPath:
false</code></li>
</ul>
</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.9...v5.5.10">https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.9...v5.5.10</a></p>
<h2>fix typins and matcher instance in callbacks</h2>
<p>combine typings file to avoid configuration changes
pass readonly instance of matcher to the call backs to avoid accidental
push/pop call</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md">fast-xml-parser's
changelog</a>.</em></p>
<blockquote>
<p><!-- raw HTML omitted -->Note: If you find missing information about
particular minor version, that version must have been changed without
any functional change in this library.<!-- raw HTML omitted --></p>
<p>Note: Due to some last quick changes on v4, detail of v4.5.3 &
v4.5.4 are not updated here. v4.5.4x is the last tag of v4 in github
repository. I'm extremely sorry for the confusion</p>
<p><strong>5.7.2 / 2026-04-25</strong></p>
<ul>
<li>allow numerical external entity for backward compatibility</li>
<li>fix <a
href="https://redirect.github.com/NaturalIntelligence/fast-xml-parser/issues/705">#705</a>:
attributesGroupName working with preserveOrder</li>
<li>fix <a
href="https://redirect.github.com/NaturalIntelligence/fast-xml-parser/issues/817">#817</a>:
stackoverflow when tag expression is very long</li>
</ul>
<p><strong>5.7.1 / 2026-04-20</strong></p>
<ul>
<li>fix typo in CJS typing file</li>
</ul>
<p><strong>5.7.0 / 2026-04-17</strong></p>
<ul>
<li>Use <code>@nodable/entities</code> v2.1.0
<ul>
<li>breaking changes
<ul>
<li>single entity scan. You're not allowed to user entity value to form
another entity name.</li>
<li>you cant add numeric external entity</li>
<li>entity error message when expantion limit is crossed might
change</li>
</ul>
</li>
<li>typings are updated for new options related to process entity</li>
<li>please follow documentation of <code>@nodable/entities</code> for
more detail.</li>
<li>performance
<ul>
<li>if processEntities is false, then there should not be impact on
performance.</li>
<li>if processEntities is true, but you dont pass entity decoder
separately then performance may degrade by approx 8-10%</li>
<li>if processEntities is true, and you pass entity decoder separately
<ul>
<li>if no entity then performance should be same as before</li>
<li>if there are entities then performance should be increased from past
versions</li>
</ul>
</li>
</ul>
</li>
<li>ignoreAttributes is not required to be set to set xml version for
NCR entity value</li>
</ul>
</li>
<li>update 'fast-xml-builder' to sanitize malicious CDATA and comment's
content</li>
</ul>
<p><strong>5.6.0 / 2026-04-15</strong></p>
<ul>
<li>fix: entity replacement for numeric entities</li>
<li>use <code>@nodable/entities</code> to replace entities
<ul>
<li>this may change some error messages related to entities expansion
limit or inavlid use</li>
<li>post check would be exposed in future version</li>
</ul>
</li>
</ul>
<p><strong>5.5.12 / 2026-04-13</strong></p>
<ul>
<li>Performance Improvement: update path-expression-matcher
<ul>
<li>use proxy pattern than Proxy class</li>
</ul>
</li>
</ul>
<p><strong>5.5.11 / 2026-04-08</strong></p>
<ul>
<li>Performance Improvement
<ul>
<li>integrate ExpressionSet for stopNodes</li>
</ul>
</li>
</ul>
<p><strong>5.5.10 / 2026-04-03</strong></p>
<ul>
<li>increase default entity explansion limit as many projects demand for
that</li>
<li>performance improvement
<ul>
<li>reduce calls to toString</li>
<li>early return when entities are not present</li>
<li>prepare rawAttrsForMatcher only if user sets <code>jPath:
false</code></li>
</ul>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/0f08303189d541b08401d15a7137dc238a815fa7"><code>0f08303</code></a>
fix typo</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/f529642d760ef53bb9115ad4798af5dc77ac22c4"><code>f529642</code></a>
update to release v5.7.0</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/52a8583465d6a67ad19e86fe34714879a981c18e"><code>52a8583</code></a>
Revert "improve performance of attributes reading"</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/8d187f9abaf42ebdd85623a9ae942b08e8ae5d0c"><code>8d187f9</code></a>
update builder</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/e174168a72a65a8fccad2c42bde329d2167edf27"><code>e174168</code></a>
improve performance of attributes reading</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/79a8dde50cebaeeda75cc1ad5b97c328da106316"><code>79a8dde</code></a>
update docs</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/f5cd5a595f313ed7b0820cabfa82ebdaa08651f7"><code>f5cd5a5</code></a>
set xml version to decoder even if attributes are ignored</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/f44b9236f4bee07bba75f0549fe86c981b1aeeef"><code>f44b923</code></a>
remove unwanted tests</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/869ec8b3588304a3a6aa9f22e38445e06d4547c8"><code>869ec8b</code></a>
Use <code>@nodable/entities</code> v2.1.0</li>
<li><a
href="https://github.com/NaturalIntelligence/fast-xml-parser/commit/7cb49e51cd060caecf296fbf718a98d8c044c8c5"><code>7cb49e5</code></a>
update release detail</li>
<li>Additional commits viewable in <a
href="https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.8...v5.7.1">compare
view</a></li>
</ul>
</details>
<br />
Updates `postcss` from 8.5.6 to 8.5.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/releases">postcss's
releases</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code></style></code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's
changelog</a>.</em></p>
<blockquote>
<h2>8.5.10</h2>
<ul>
<li>Fixed XSS via unescaped <code></style></code> in non-bundler
cases (by <a
href="https://github.com/TharVid"><code>@TharVid</code></a>).</li>
</ul>
<h2>8.5.9</h2>
<ul>
<li>Speed up source map encoding paring in case of the error.</li>
</ul>
<h2>8.5.8</h2>
<ul>
<li>Fixed <code>Processor#version</code>.</li>
</ul>
<h2>8.5.7</h2>
<ul>
<li>Improved source map annotation cleaning performance (by CodeAnt
AI).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/postcss/postcss/commit/33b9790263dc1562a46ce45d9532bd63e95b7986"><code>33b9790</code></a>
Release 8.5.10 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/536c79e4b01e58a3a56b09c3c0cf2323f4b9a28b"><code>536c79e</code></a>
Escape </style> in CSS output (<a
href="https://redirect.github.com/postcss/postcss/issues/2074">#2074</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/afa96b2a139ce625c4d27973313479c7c85f39d4"><code>afa96b2</code></a>
Update dependencies (<a
href="https://redirect.github.com/postcss/postcss/issues/2073">#2073</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/effe88bb87cabdc1876e02adbdd30f392f19f40d"><code>effe88b</code></a>
Typo (<a
href="https://redirect.github.com/postcss/postcss/issues/2072">#2072</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/3ee79a2c4a11e41d52db50b444eebe38299495ad"><code>3ee79a2</code></a>
Thread model (<a
href="https://redirect.github.com/postcss/postcss/issues/2071">#2071</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/2e0683daca4dc2919211b03774f6b2d137136c01"><code>2e0683d</code></a>
Create incident response docs (<a
href="https://redirect.github.com/postcss/postcss/issues/2070">#2070</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/fe88ac29c06b7b218be32994cdc6ca1525bdf2c9"><code>fe88ac2</code></a>
Release 8.5.9 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/c551632496b87ab3f1965bfda5dc386b6c71963e"><code>c551632</code></a>
Avoid RegExp when we can use simple JS</li>
<li><a
href="https://github.com/postcss/postcss/commit/89a6b744060eb8dee743351c785a9fbe37d4525a"><code>89a6b74</code></a>
Move SECURITY.txt for docs folder to keep GitHub page cleaner</li>
<li><a
href="https://github.com/postcss/postcss/commit/6ceb8a46af9f9de821faee98f861bdf84617347b"><code>6ceb8a4</code></a>
Create SECURITY.md</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.6...8.5.10">compare
view</a></li>
</ul>
</details>
<br />
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 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>
Resolves#3757
## Description:
Simple patch that would remove an extra click that users have to do each
time they create a private lobby. On top of the existing button, the
game link will automatically be copied to the clipboard when clicking
"Create Lobby".
## 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:
zixer._
## Description:
Fix: only run the deploy action within our repo. It was already meant to
do this, but the if statement had a bug.
This lead to errors in repos with a fork, because it would run but
couldn't find the needed secrets there of course.
## 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:
tryout33
## Description:
Add Luna and ArchipelagoSea to the water-nukes-boosted maps set.
Bias Luna games towards 2 teams (75% chance), similar to how FourIslands
is biased towards 4 teams.
Restrict the FourIslands gold multiplier exclusion to team games only,
since the stalemate risk is team-mode-specific. Also removes the
startingGold25M exclusion that was bundled with it. Reasoning: Did some
data analysis to find the root cause.
1M starting gold games accidentally had 45 seconds of PVP immunity, but
thats not needed.
## 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:
Small-island removal previously ran only on the full-size terrain. The
compact (4x downscaled) map inherited that filtering before being
downscaled, which meant islands that survived at full size could end up
as tiny specks in the compact map.
This PR runs `removeSmallIslands` on the 4x terrain as well, with half
the threshold (15 vs 30 tiles), so very small islands are pruned in
compact maps while the full-size map is unchanged.
## 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:
buildAssetUrl had a middle branch that, when called with a directory-ish
path (e.g. assetUrl("maps")), would check whether any manifest entry had
that prefix and return an unhashed /_assets/<path> URL. This was wrong:
* The /_assets/ prefix implies a managed, hashed asset — but the
returned URL is neither. It won't exist on R2 after the migration.
* It defeats cache-busting, since no hash is applied.
* It encourages callers to reconstruct asset paths by hand via string
concatenation, bypassing the manifest as the single source of truth.
Renaming or reorganizing an asset directory would silently break callers
the manifest can't help locate.
## 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
The proprietary/ fallback middleware was registered with `return () => {}`,
which placed it after Vite's htmlFallbackMiddleware. Browser `<img>`
requests carry `*/*` in their Accept header, so htmlFallback intercepted
them and returned index.html — meaning OpenFrontLogo.svg, Favicon.svg,
etc. silently rendered as the HTML shell.
Register the middleware up front, check resources/ first so publicDir
retains precedence, and set Content-Type via mrmime so browsers actually
render the SVGs.
Part of #2661 (split into 3 PRs so they are not too large..)
## Description:
Part 1/3 of #2661.
This PR adds warship retreat basics, a blue retreating UI state, and
updates target priority.
Added:
- Retreat state handling
- Blue visual for retreating warships
- Target priority: transport > warship > trade
- Tests for retreat and target priority
Example video:
https://youtu.be/2hE2qeOeY48
Ship retreating:
<img width="630" height="488" alt="image"
src="https://github.com/user-attachments/assets/56d3e6d5-08af-453d-afe5-ee21dd6f3414"
/>
Ship healing:
<img width="483" height="311" alt="image"
src="https://github.com/user-attachments/assets/aeaf2239-bb81-444f-84ef-62dbcb48fddf"
/>
Back to being deployed:
<img width="585" height="358" alt="image"
src="https://github.com/user-attachments/assets/875828a2-8a24-4593-ac76-26426bb81057"
/>
## 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:
zixer._