## What
Removes the binary **dark mode** feature and replaces it with a
player-adjustable **Lighting** section in graphics settings.
### In-game settings
- Removed the Dark Mode toggle from both `SettingsModal` and
`UserSettingModal`, and `darkMode()`/`toggleDarkMode()`/`DARK_MODE_KEY`
from `UserSettings`.
### New Lighting section (Graphics Settings)
- **Ambient light** slider (1–3): mapped to the renderer's ambient as
`ambient = 1 / level`. **1.0 = no effect (unchanged look), 3.0 = darkest
with the strongest structure glow.**
- **Light falloff** slider (1–3): writes straight to
`lighting.falloffPower`.
- Lighting auto-enables only when ambient < 1, so the default (slider at
1) has zero GPU cost — off by default.
### Removed dark-mode overrides
- Deleted `applyDarkModeOverride()` + `DARK_AMBIENT` and their wiring in
`ClientGameRunner`, `gl/index.ts`, and the `DARK_MODE_KEY` listener.
- Removed the `.dark` HUD-class toggle in `Main.ts` and the
`userSettings.darkMode()` read in `PlayerIcons`.
### Train glow
- `UT_TRAIN` light reduced (intensity `2.0 → 0.5`, radius `8 → 6`) so
structures dominate the glow.
## Notes
- Removing the dark-mode setting also retires the HUD's Tailwind dark
theme (same setting). The dormant `dark:` CSS variants and unused
white-icon assets are left in place (out of scope).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
## What
Adds a **Terrain** section to the graphics settings modal with a color
picker and a hex-code text field (paste a `#rrggbb` code) for the
**ocean** (deep water) color.
## Details
- The picked color sets the *shallow-water base*; the existing per-depth
brightness gradient is preserved (deeper water still darkens).
- Only deep water is affected — shoreline water and land are untouched.
- Follows the same override pattern as every other graphics setting: the
default lives in `render-settings.json` (`terrain.oceanColor`), the
override is a field in `GraphicsOverrides`, and `applyGraphicsOverrides`
copies it into the live `RenderSettings`.
- Rebased on #4271 (settings resolved before renderer construction): the
terrain texture **bakes the resolved ocean color at construction**, so a
saved override shows on load with no special-casing. Terrain is baked
into a GPU texture rather than read per-frame, so a *live* change still
triggers an explicit `view.rebuildTerrain()`.
- Resetting graphics overrides clears it back to the default ocean
color.
## Testing
Verified live in a headless singleplayer game:
- A **saved** ocean override renders green deep-water on load, baked at
construction with no settings-change event fired.
- A mid-game color change recolors the deep ocean instantly, gradient
preserved, shoreline/land untouched.
`tsc` and ESLint clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
## Summary
Adds a new **Structure icon size** option to `GraphicsOverrides`,
exposed as a slider in the Graphics Settings modal. Players can now
scale how large structure icons are drawn on the map.
## Changes
- **`GraphicsOverrides.ts`** — add `iconSize: z.number()` to the
`structure` override schema.
- **`RenderOverrides.ts`** — apply the override onto
`settings.structure.iconSize` (consumed by
`StructurePass`/`StructureLevelPass` shaders).
- **`GraphicsSettingsModal.ts`** — add a slider (range 20–120, step 5)
in the "Structure Icons" section, with getter/handler following the
existing pattern. Falls back to the `render-settings.json` default of 60
when unset.
- **`resources/lang/en.json`** — add `icon_size_label` /
`icon_size_desc` (English only, per i18n rules).
- **`tests/GraphicsOverrides.test.ts`** — schema-validation cases plus
application tests (override sets the value; absence keeps the default).
The setting persists via the existing `userSettings.graphicsOverrides()`
localStorage flow and takes effect live through the existing
`regenerateRenderSettings` wiring.
## Testing
- `npx vitest tests/GraphicsOverrides.test.ts --run` — 35 passed
- `tsc --noEmit` — no new type errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
## What
Structure **level numbers** now render in the **`round_6x6_modified`**
bitmap font by default (matching the old PIXI-based `StructureLayer` /
`v31`), with a graphics setting to switch back to the smooth
`overpass-bold` MSDF font.
Two commits:
1. **Default to the classic bitmap font** — `StructureLevelPass` drew
level digits from the `overpass-bold` MSDF atlas (the one `NamePass`
uses for player names); switch the default to the `round_6x6_modified`
pixel font (white digits with a baked-in dark outline).
2. **Add a runtime toggle** — load both fonts and switch between them
live via a new `Classic level numbers` graphics setting.
## How
- `StructureLevelPass` loads both atlases up front and selects one per
frame from `settings.structureLevel.classicFont`, re-laying-out the
digits when the toggle flips (digit advances differ between the fonts).
The fragment shader is a single program with a `uClassic` branch: direct
bitmap sample (white fill + baked outline) vs. MSDF median + synthesized
outline.
- New override `structure.classicNumbers` in `GraphicsOverrides`
(default `true` = classic), applied onto
`settings.structureLevel.classicFont` in `applyGraphicsOverrides` — so
it switches live, like the existing colorblind/classic-icons toggles.
- `GraphicsSettingsModal` gets a `Classic level numbers` toggle next to
`Classic icons` (with `en.json` strings).
## Testing
- `tsc --noEmit`, ESLint, Prettier, and `npm run build-prod` all pass.
- Ran the game headless, built/upgraded cities to level 2–3, and
confirmed: the classic toggle renders the pixel font, flipping it
renders the smooth MSDF font, and flipping back restores the pixel font
— switching live with no shader errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Resolves#4250
## Description:
Huge update for the map categories:
https://github.com/user-attachments/assets/b7dc6344-efdc-4073-b15a-92b6dccdcc19
**New Categories**
- Re-adds Continental category, with the 7 traditional continents
- Re-adds the category of Arcade along all its maps.
- Renames "Other" to "Fictional", so that tag is more specific and feels
more in-theme with the others. The info.json's of the maps that had the
Other category got changed to Fictional
**Map Category changes**
- **achiran**: adds Europe (while the map is fictional, it is made up of
real islands from ireland. (Since world includes Dyslexdria and
Antarctica has Deglaciated Antarctica, both fictional , i figured for
consistency we could include these mash-up maps too)
- **aegean**: adds Asia category (Turkey is in Asia)
- **arctic**: adds Asia category
- **choppingblock**: updated "other" to "fictional", added to "new"
- **deglaciatedantarctica**: updated "other" to "fictional"
- **didier**: re-added to Arcade
- **didierfrance**: re-added to Arcade
- **dyslexdria**: updated "other" to "fictional"
- **fourislands**: updated "other" to "fictional"
- **hawaii**: remove north_america tag (while part of the US, hawaii is
geographically only in Oceania)
- **labyrinth**: added to new, re-added to Arcade
- **marenostrum**: added africa and asia tags, the continents which the
mediterranean borders
- **onion**: re-added to Arcade
- **pangaea**: updated "other" to "fictional"
- **passage**: updated "other" to "fictional"
- **sierpinski** re-added to Arcade
- **surrounded**: updated "other" to "fictional"
- **svalmel**: updated "other" to "fictional", added to europe and
north_america (same logic as achiran)
- **thebox**: re-added to Arcade
- **tradersdream**: updated "other" to "fictional"
- **worldinverted**: updated "other" to "fictional", added to "new"
- **africa**: added to Continental
- **antarctica**: added to Continental
- **asia**: added to Continental
- **europe**: added to Continental
- **northamerica**: added to Continental
- **southamerica**: added to Continental
- **oceania**: added to Continental
- **mississippiriver**: added to "new"
- **korea**: added to "new"
- **middleeast**: added to "new"
- **balkans**: added to "new"
- **indiansubcontinent**: added to "new"
- **taiwanstrait**: added to "new"
- **northwestpassage**: added to "new"
- **southeastasia**: added to "new"
- **venice**: added to "new"
- **yellowsea**: added to "new"
- **hongkong**: added to "new"
- **titan**: added to "new"
- **caribbean**: added to "new"
- **juandefucastrait**: added to "new"
- **danishstraits**: added to "new"
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
tri.star1011
## Description:
Version identifier within MLS: v5.5
[Changed languages]
- eo
- fa
- fr
- hu
- ja
- ru
- uk
[Change volume]
- Changed languages: 7
- Changed files: 7
- Changed lines: 17353
- metadata.json: unchanged
Final reviewer: name
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
> **Before opening a PR:** discuss new features on
[Discord](https://discord.gg/K9zernJB5z) first, and file bugs or small
improvements as
[issues](https://github.com/openfrontio/OpenFrontIO/issues/new/choose).
You must be assigned to an `approved` issue — unsolicited PRs will be
auto-closed.
**Add approved & assigned issue number here:**
Resolves#4259
## Description:
2 Warship shaped islands next to each other. Trade ships and land
attacks can go through the corners. This can be either a 2 teams or a
ffa map. Size is 3000x1396 with 29% land. This will complete the 20th
map for v32 before it releases in 2 days.
There are 10 nations with 23 additional nations (with ai generated
names). The nations are made up similarly to the ones in traders dream
but they are piracy themed and theres also a meme "Evil island man"
nation (rex reference)
It is based on a meme when Ultimus-Rex says "warship warship" when
deploying warships and now people spam "warship warship" in the
comments, especially this user named @warshipwarship who comments
warship warship on every video.
[https://youtu.be/DGMIji0bQQM](https://github.com/openfrontio/OpenFrontIO/issues/url)
<img width="3000" height="1396" alt="image"
src="https://github.com/user-attachments/assets/4bf6d708-afbc-41ea-be7c-cf43fdf69cbc"
/>
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
DISCORD_USERNAME crunchybbbbb
Resolves#4169
## Description:
Adds a delayed lobby start option.
Utilizes the same system as for public lobbies.
The default for the option is for lobbies to take 3 seconds to start,
however this can easily be changed.
The current setting is controlled through an enable-disable slider,
however there are multiple other options for how to control this.
For example we could do a slider, an input field, a dropdown etc. And i
dont necessarily know if the currently implemented option is the best.
Furhtermore im not sure if i have used the language file completely
correctly. There is now a duplicate field for both private and public
lobby. However there is not category shared between the two. So i
decided to reuse the field from public for private games, as this
simplified the code a bit.
**Host video**
https://github.com/user-attachments/assets/6f3db6e4-7323-4fad-8544-efb8cef4d969
**Non-host video**
https://github.com/user-attachments/assets/ee02a072-1f42-4dde-a5d9-120fda862eb7
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
FrederikJA
**Add approved & assigned issue number here:**
N/A — maintainer change, groundwork for #4231.
## Description:
One-time recursive key sort of `resources/lang/en.json` (`jq -S` +
prettier), with a test (`tests/EnJsonSorted.test.ts`) that enforces the
invariant from now on.
Why: sorted keys make the file deterministic, give translation PRs
stable insertion points instead of everyone appending at section ends,
and let the map-generator (#4231) rewrite the en.json map section with a
plain JSON unmarshal/marshal round-trip — Go's `encoding/json` sorts
object keys on marshal, so under this invariant a full-file rewrite is a
no-op for everything it doesn't change.
Crowdin matches translation entries by key path, not file position, so
existing translations are unaffected. Only en.json is touched and
checked; other language files remain Crowdin-managed (they may get
reordered by Crowdin's next export, which is cosmetic).
The diff is 100% line moves — no key or value changes (JSON-equal before
and after).
## Please complete the following:
- [x] I have added screenshots for all UI updates (no UI changes)
- [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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
evanpelle
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
**Add approved & assigned issue number here:**
Resolves#3839
## Description:
A bunch of small updates to make the coordinate grid a lot nicer.
- Removes black backgrounds on text.
- Allows user to modify the opacity of the coordinate grid
- Persist the enable state of the coordinate grid
### Before
<img width="2344" height="1168" alt="image"
src="https://github.com/user-attachments/assets/22c2fb77-9db6-41bf-a50a-987f651cc19a"
/>
### After
<img width="2331" height="1174" alt="image"
src="https://github.com/user-attachments/assets/0e5a9575-8a79-407b-8d78-8564df02b259"
/>
<img width="407" height="947" alt="image"
src="https://github.com/user-attachments/assets/b9e5f9f1-3cc1-4832-b7d4-38e1f5e93d57"
/>
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
FrederikJA
**Add approved & assigned issue number here:**
N/A — maintainer refactor.
## Description:
Makes each map's `info.json` the single source of truth for map metadata
— adding a map is now a folder with `image.png` + `info.json`, a
`gen-maps` run, and an en.json display name.
**info.json / manifest.json carry full map metadata.** Every
`map-generator/assets/maps/<map>/info.json` declares `id` (the
`GameMapType` enum key), `name` (the enum value — wire format, unchanged
for all 94 maps), `translation_key`, `categories`, and
`multiplayer_frequency` (the public-playlist weight that used to be the
`FREQUENCY` record in MapPlaylist.ts). The generator validates
everything and mirrors it into `resources/maps/<map>/manifest.json`. 23
stale info.json `name` values were normalized to the canonical enum
value; enum values are byte-identical, so replays and stored game
configs are unaffected.
**The generator emits the TypeScript and discovers maps itself.** New
`map-generator/codegen.go` generates `src/core/game/Maps.gen.ts`
(`GameMapType`, `GameMapName`, `mapCategories`, `mapTranslationKeys`,
`multiplayerFrequency` — now a full `Record<GameMapName, number>`,
killing the old `Partial`) on every run; `Game.ts` re-exports it. The
hardcoded map registry in `main.go` is gone — maps are auto-discovered
from the `assets/maps` / `assets/test_maps` directories. MapConsistency
tests fail with a "run `npm run gen-maps`" message if info.json,
manifest.json, and Maps.gen.ts drift. The tracked
`map-generator/map-generator` binary is rebuilt to match.
**New categories: continents + world/cosmic/tournament/other,
multi-category support.** `continental`/`regional`/`fantasy`/`arcade`
are replaced by `featured`, `world`, `europe`, `asia`, `north_america`,
`africa`, `south_america`, `oceania`, `antarctica`, `cosmic`,
`tournament`, and `other`. Maps can list multiple categories, so
straddlers (Black Sea, Bosphorus, Caucasus, Between Two Seas, Bering
Sea/Strait, Mena, Strait of Gibraltar, Hawaii, Arctic) appear under both
regions. Featured is itself a category (same 7 maps as before).
MapPlaylist keeps its arcade exclusion via an explicit set.
**Map picker UI.** Two tabs: **Featured** (default — featured maps plus
a Favorites section when maps are starred) and **All** (one prominent
collapsible bar per category with a map count, collapsed by default).
The selected map is prepended to the featured grid when it lives
elsewhere. `getMapName()` resolves through the generated
`mapTranslationKeys`, which also fixes tourney maps never resolving a
valid translation key.
## Please complete the following:
- [ ] I have added screenshots for all UI updates (maintainer change —
picker described above)
- [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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
evanpelle
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The hovered player (tile owner under the cursor, already tracked via
uHighlightOwnerID for cull bypass) now gets a soft white glow behind
their name. The glow is derived from the MSDF distance field: a white
band past the outline with quadratic falloff, composited behind the
glyph and clamped to the SDF margin so it never clips at quad edges.
Glow size and strength are tunable via hoverGlowWidth/hoverGlowAlpha
in render-settings.json, exposed as sliders in the graphics settings
modal (persisted as graphics overrides) and in the debug GUI.
Includes schema and apply tests for the new override fields,
covering the 0 edge case (0 disables the glow, not "unset").
The clan-tag ownership check previously failed closed: when the API
service was unreachable (e.g. during local development), the client
dropped the tag with a "couldn't verify" error and the server's
FailOpenPrivilegeChecker treated every unverifiable tag as reserved.
This made clan tags unusable whenever the API was down.
- Client: checkClanTagOwnership keeps the tag when the existence
probe is inconclusive; the server still re-checks authoritatively.
- Server: FailOpenPrivilegeChecker passes tags through instead of
dropping non-member tags; decideClanTag now takes a non-nullable
reserved set since the null case is gone.
- Remove the now-unused username.tag_check_failed translation key.
- Update Privilege and ClanApiQueries tests for fail-open behavior.
Trade-off: if the reserved-tag list is unavailable in production,
real clan tags can be impersonated until the first successful
PrivilegeRefresher load; after that the last good checker is retained.
Resolves#3900
## Description:
During the spawn phase in FFA games, display a collusion warning to
clearly communicate to new users that pre-game agreement is not allowed.
<img width="1362" height="662" alt="2026-06-01_20-31"
src="https://github.com/user-attachments/assets/bd083e91-280a-41e1-a11a-d69d5f16bc8a"
/>
- [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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
goose126
---------
Co-authored-by: evanpelle <evanpelle@gmail.com>
Resolves#4182
## Description:
Adds "Titan" (real moon of Saturn with methane seas) map . Uses new
random spawn nation feature by FloPinguin.
https://github.com/openfrontio/OpenFrontIO/pull/4156
Also adds new Cosmic map category. The "Other" map category has become a
wastebasket of unrelated maps, and with increasing number of maps, i
think its a good addition to have better categories for these maps.
I figured these 2 changes should go together since im adding a cosmic
map, and a cosmic category.
proof of nations spawning randomly and how the cosmic category looks in
the menu:
https://github.com/user-attachments/assets/b84bd3ef-6b8f-46fe-a6ea-ea5e79c6dc00
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
tri.star1011
---------
Co-authored-by: Evan <evanpelle@gmail.com>
**Add approved & assigned issue number here:**
Resolves#2549
## Description:
Adds colorblind mode. Similar to dark mode, it exists as a toggle in
settings. When enabled, it swaps the game's theme (which is refactored
to extend from a theme base class) to use more colorblind-friendly
colors and brightness variations. Borders are darkened, and terrarin is
separated by lightness. Friendly/Foe colors and switched to blue/orange
instead of red/green.
The theme refactor supports adding new themes without having to
reimplement the color distribution system. New themes can extend the
BaseTheme and supply the data, such as palettes, team-color variations,
and terrain.
New setting:
<img width="880" height="273" alt="Screenshot 2026-06-04 at 11 30 27 AM"
src="https://github.com/user-attachments/assets/d5d573d5-cc64-4ac1-95c2-00627faf17cc"
/>
New color palette:
<img width="1119" height="757" alt="Screenshot 2026-06-04 at 11 30
59 AM"
src="https://github.com/user-attachments/assets/2bb15bc9-992b-41ae-ab0e-b01fe0c3c6bb"
/>
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
jetaviz
## Description:
Player name plates can block the view of what's underneath them
(structures, units, terrain). This PR fades the entire name plate —
name, troop count, flag, and emoji/status row — to 25% opacity while the
cursor is over it, so you can see and click what's behind it.
**How it works:**
- `HoverHighlightController` pushes the cursor's world position into the
renderer on mouse move.
- `NamePass` hit-tests the cursor against each player's name plate
bounds on the CPU (mirroring the lerp/sizing math in `name.vert.glsl`)
and passes the matched player's ID to the text, icon, and status-icon
programs, which apply the alpha multiplier in their shaders.
**Graphics setting:**
- New "Name opacity under cursor" slider in the Graphics Settings modal
(Name Labels section), range 0–1, default 0.25. Setting it to 1 disables
the fade entirely.
- Wired through the existing `GraphicsOverrides` pipeline: changes apply
live and are cleared by "Reset to defaults".
- Tuning knob exposed as `name.hoverFadeAlpha` in `render-settings.json`
and the debug GUI.
## Please complete the following:
- [ ] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
## Please put your Discord username so you can be contacted if a bug or
regression is found:
evan
Resolves#4148
## Description:
Adds "Juan de Fuca Strait" map. This is the Strait in Washington and
British Columbia: https://en.wikipedia.org/wiki/Strait_of_Juan_de_Fuca
This map is meant to be a brand new 3-team way map, since all the team
maps we have are either made for 2 or 4 teams.
The map is bumped towards this gamemode similar to how Baikal is bumped
to 2 teams.
Map also has Additional Nations, for a total fof 62, for Human vs
Nations and solo games
<img width="1365" height="602" alt="image"
src="https://github.com/user-attachments/assets/9cb86727-db06-4fcb-bee4-85e7b5d47d15"
/>
<img width="1319" height="488" alt="image"
src="https://github.com/user-attachments/assets/13fd9a01-7ec6-49ab-81c3-40b566cbf6e0"
/>
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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
tri.star1011
Local-player rails previously rendered in the white focused-border color
from the palette, making them hard to see on light territory. Rails now
use a dedicated local rail color: white normally, flipped to black when
the territory backdrop is too light for white to read against (patterns
average their primary/secondary brightness).
Also add a railThickness render setting (0.5-3, default 1), exposed in
the Graphics Settings modal and the debug GUI, and persisted via
GraphicsOverrides. In the medium-zoom LOD, rails are now drawn as
screen-space anti-aliased lines around each tile's rail centerline,
accumulated from the 3x3 neighborhood so thick lines spill cleanly into
neighboring tiles; detailed mode scales its sub-grid band widths.
- PlayerView: compute railColor() (white/black by backdrop brightness)
- RailroadPass/shader: uLocalPlayerID, uLocalRailColor, uRailThickness
- render-settings.json, RenderSettings, GraphicsOverrides,
RenderOverrides: new railroad.railThickness knob
- GraphicsSettingsModal: "Train track thickness" slider (+ en.json keys)
- tests: schema + apply coverage for railroad overrides
Resolves https://github.com/openfrontio/OpenFrontIO/issues/3445
## Description:
I copied the PR #3743 from @luctrate (Add army limit warning indicator
for team games) to this PR because he didn't respond to requested
changes but I thought it's important.
I expanded on it, now its a full help message system:
**Warnings (orange):**
- Army limit: shown in team games with donations when troops exceed 80%
of max
- Low troops: shown when troops drop below 1k (=> new noob player who
clicks too much)
<img width="764" height="251"
alt="582494157-cf19b13e-a0a9-44e4-8de8-86c007fe9c79"
src="https://github.com/user-attachments/assets/6b4996d9-1993-4d2c-98ba-afba17a5ca4d"
/>
**Info messages (blue):**
- Borders a traitor ally: "You can betray traitors without becoming a
traitor yourself" (Because its not obvious for new players)
- Borders an allied AFK player: "You can attack disconnected players
even if you are allied with them" (Because its not obvious for new
players)
- Borders an AFK teammate: "You can attack disconnected teammates"
(Because its not obvious for new players)
Info messages only appear when the player has not attacked the relevant
neighbor for at least 15 seconds, so they do not show up without reason.
<img width="524" height="141" alt="image"
src="https://github.com/user-attachments/assets/88d74661-d47e-45a7-9f91-d4f5361114b7"
/>
New "Help Messages" toggle in settings (default: on)
<img width="409" height="105" alt="image"
src="https://github.com/user-attachments/assets/24bc8bed-777b-4f72-9451-02116ac39db0"
/>
Implementation details:
- Border detection uses async borderTiles() refreshed every 1s, cached
in a Set of nearby player smallIDs
- Outgoing attacks are tracked per-target to compute the 15-second idle
threshold
- New armyLimitWarningThreshold() on Config (returns 0.8)
- All user-facing strings go through translateText() with en.json
entries
AI Model used: MiMo 2.5 Pro
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
FloPinguin
Drop the "Your {unit} was captured by {name}" and "Captured {unit} from
{name}" display messages on unit ownership change in UnitImpl. They fired
on every capture — dominated by warships taking trade ships — and were
too spammy to be useful, so players tuned them out.
Also clean up the now-unused pieces:
- Remove the UNIT_CAPTURED_BY_ENEMY message type, its category mapping,
and its case in getMessageTypeClasses.
- Remove the orphaned unit_captured_by_enemy and captured_enemy_unit
en.json keys.
CAPTURED_ENEMY_UNIT is kept — still used by the trade-ship gold message.
Resolves#4202
## Description:
As suggested in some suggestions in the main OF server
[[thread](https://discord.com/channels/1284581928254701718/1472496670267805782)],
we should have a map favouriting system since there are over 70 maps
already. People (myself included) have some maps we constantly play
during solo/private matches, so a favourite tab would be huge.
This feature adds the favourites tab to the solo and private match
selection screens. It works using localStorage for saving (device
persistence) but I can just as easily implement an infra update where
players have a 1-many relation with a `FavouriteMaps` table. That can be
a future solution. Video example right now:
https://github.com/user-attachments/assets/e8e278ab-d305-499a-81a9-d570e05db051
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
bijx
> **Before opening a PR:** discuss new features on
[Discord](https://discord.gg/K9zernJB5z) first, and file bugs or small
improvements as
[issues](https://github.com/openfrontio/OpenFrontIO/issues/new/choose).
You must be assigned to an `approved` issue — unsolicited PRs will be
auto-closed.
**Add approved & assigned issue number here:**
Resolves#4154
## Description:
Adds a join path from reserved clan tag warnings to the clan detail
modal.
https://github.com/user-attachments/assets/cc0f4cb8-be8e-414a-8147-7a744069999e
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
aotumuri
Expose two new user-configurable map-overlay controls in the graphics
settings modal: territory saturation (mutes fill colors toward grayscale)
and territory opacity (lets terrain show through the fill).
The territory fragment shader blends the fill toward its luminance based
on uSaturation and applies uTerritoryAlpha as the absolute fill opacity.
Both are wired through RenderSettings, the GraphicsOverrides schema,
applyGraphicsOverrides, the debug Layout sliders, and TerritoryPass
uniforms, with defaults (saturation 1, alpha 0.588) in render-settings.json.
Adds the corresponding en.json label/description strings.
> **Before opening a PR:** discuss new features on
[Discord](https://discord.gg/K9zernJB5z) first, and file bugs or small
improvements as
[issues](https://github.com/openfrontio/OpenFrontIO/issues/new/choose).
You must be assigned to an `approved` issue — unsolicited PRs will be
auto-closed.
**Add approved & assigned issue number here:**
Resolves #4152(issue number)
## Description:
- Adds a map of Hong Kong. The size is 2781x1997 with land area of 41%
(2.2mil pixels). The islands, straits, harbors, coastlines and
peninsulas make for some very intersting gameplay.
- HK is the second densest place on earth. To simulate this, there are
71 nations based on districts, parks, islands, etc. (Kowloon and HK
Island are so crowded with nations, there may be only 1-2 tribes that
spawn there!)
- Large coastal plains, passes and mountain ranges across islands and
the mainland
map image
<img width="2781" height="1997" alt="hk-improvedriver"
src="https://github.com/user-attachments/assets/ef324fca-88f7-487c-adb0-fa31fc370458"
/>
showcase https://www.youtube.com/watch?v=DosBDttQVmE
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
DISCORD_USERNAME crunchybbbbb
---------
Co-authored-by: RickD004 <realtacoco@gmail.com>
The special effects toggle wrote settings.specialEffects but nothing in
the WebGL pipeline read it — the FX pass is gated on passEnabled.fx. The
setting was orphaned when the old canvas renderer was removed, so the
toggle had no visual effect.
Move the toggle into the graphics settings modal (under a new Effects
section) and remove it from the in-game settings modal and the homepage
user settings modal. Rewire it to a passEnabled.fx graphics override so
it actually toggles the FX pass, applied live via the existing graphics
override listener.
Delete the now-dead fxLayer()/toggleFxLayer() from UserSettings.
Note: users who previously disabled special effects will reset to on,
since the old settings.specialEffects key is no longer read.
Extend GraphicsOverrides with a mapOverlay group (territory highlight,
border highlight amount, border highlight thickness) and a railroad
group (train track draw distance), wired through the schema,
applyGraphicsOverrides, and new sliders in the graphics settings modal.
Fix the territory hover highlight: the shader received uHighlightBrighten
but ignored it, applying a hardcoded saturation boost so the setting had
no effect. It now drives a contrast boost (push channels away from
mid-gray), with 0 disabling the effect.
The train track slider is presented as a "draw distance" (inverted
railMinZoom) so higher = tracks stay visible when more zoomed out.
Also move the Graphics settings button to the top of the settings modal.
Resolves#4187
## Description:
Add Map - World Inverted
1248x2500, 1,561,000 land tiles
~100 standard. Over 250+ total.
https://www.youtube.com/watch?v=w2LVZQXZoaUhttps://discord.com/channels/1284581928254701718/1509034328766812210
## 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
## Please put your Discord username so you can be contacted if a bug or
regression is found:
PlaysBadly
Resolves#4080
## Description:
Add Map Chopping Block
https://youtu.be/NpX73lHiKO8
Increased multiplier for 4 player team games and water nukes (plug in
center among other shortcuts). This map was made as a faster alternative
to Labyrinth. Map has been modified since last submission to be 'less
crazy'.
## 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
## Discord username:
PlaysBadly
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves #(issue number)
## Description:
adds a check to see if you're in a clan or not. if not, checks to see if
the clan exists, if it does, warns the user, if it doesn't, lets them
use it.
## 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#4098
## Description:
Adds Southeast Asia map for v32. Very requested map. 31 default nations
(with an extra 31 named for HvN).
Map for intense warship and naval warfare with many, many islands. Also
adds flags of the region to be used by nations in the map. More info
specified in issue
https://github.com/user-attachments/assets/b4151db4-825a-4c1c-8bf8-7b760ae056d2
## 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:
Version identifier within MLS: v5.4
[Changed languages]
- bg
- eo
- fa
- fr
- hu
- ja
- ru
- uk
- zh-CN
[Change volume]
- Changed languages: 9
- Changed files: 9
- Changed lines: 17653
- metadata.json: unchanged
Final reviewer: meow
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
Show bonus amount on currency packs
- Add `bonusAmount` field to `PackSchema` (non-negative int)
- Render a rotated green corner ribbon (`+X FREE!`) on pack tiles when
`bonusAmount > 0`
- Add `cosmetics.free` translation key with `numFree` param
<img width="720" height="359" alt="Screenshot 2026-05-12 at 7 40 12 AM"
src="https://github.com/user-attachments/assets/3dd70fc4-c922-47f4-aee6-055047b58563"
/>
Describe the PR.
- [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
regression is found:
evan
## Description:
Fixes#4069
Adds map of the Caribbean sea and its islands. Archipelago map with lots
of islands, lots of water and a lot of trade.
This map has multiple large landmasses of similar size to prevent
steamrolls (the largest islands and landmasses are around 30%), and
many, many small islands where players can survive and trade. Players
will have to island hop in order to win. 34 nations of Caribbean
countries and territories, with an extra 28 AdditionalNations for a
total of 62 nations for crowded HvN.
Heavy Island maps are very popular in the broader community and we dont
have one for v32, so i figured it would be nice to have a very requested
and popular world location
570k land tiles, fairly small for a map, would be right placed before
World (600k tiles). Also adds some flags of caribbean regions.
https://github.com/user-attachments/assets/9eae81ec-58eb-4594-89fd-2f95742f8b3a
Terrain source from OpenTopography, already credited. No modification to
the tests are needed for new maps added in Game.ts
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
tri.star1011
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves#4055
## Description:
Adds a 512*512 onion map with 3 nations (Leafer Confederation, Outer
Enclave and Inner Tribe)
<img width="128" height="128" alt="thumbnail"
src="https://github.com/user-attachments/assets/8d97d8dc-6286-4e79-a459-767c936d49ec"
/>
## 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:
tktk1234567
## Description:
"A high-stakes naval theater where empires clash over narrow corridors,
bottleneck straits, and heavily fortified shorelines."
Modeled to the exact strategic proportions of the classic Black Sea map,
Yellow Sea shifts the focus of global conflict to East Asia. The map is
defined by its massive central body of water, making naval dominance
absolutely essential for survival. However, unlike wide-open oceans,
control of the Yellow Sea is entirely dictated by its unique coastal
geography.
The Shandong And Liaoning Peninsulas are The definitive feature of the
map. Two massive, opposing peninsulas project deep into the sea, acting
as natural, heavily contestable daggers. They create tight naval choke
points in the central waters while forcing land-based players into
brutal, linear frontlines where every pixel of territory is bought with
blood.
The Continental Rim: A sprawling mainland coast wraps around the
northern and western edges of the map, offering expansive land routes
for players who prefer sweeping land invasions over amphibious assaults.
Scale Class: Medium
Gameplay Style: Naval/Land Hybrid, Tactical Choke Points, Frontline
Bottlenecks
Nations: 8
North Korea South Korea Liaoning Shandong Beijing Hebei Tianjin Jilin
description mostly generated by google gemini ai
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
DISCORD_USERNAME crunchybbbbb
<img width="1660" height="1266" alt="Screenshot 2026-05-24 220103"
src="https://github.com/user-attachments/assets/800c6732-677d-44f1-ba5c-c60da5f199e0"
/>
<img width="1500" height="1152" alt="yellow_sea2"
src="https://github.com/user-attachments/assets/9b3ba34a-3f9c-4485-9235-f953fd07be4c"
/>
Game play video https://youtu.be/IcRPTM0rHM0
---------
Co-authored-by: RickD004 <realtacoco@gmail.com>
The structureSprites toggle was only read by the toggle UIs themselves —
no rendering code ever consulted it. Drops the getter/setter from
UserSettings, both toggle rows (SettingsModal + UserSettingModal), and
the en.json keys. Other-language entries are left for Crowdin to reap.
Adds a "Classic icons" toggle in the structure-icons section of the
Graphics Settings modal. Off (default) keeps today's renderer look;
on switches to a classic style — lighter player-colored shape behind
a dark icon glyph, with 0.75 alpha for a subtle translucent feel.
Exposes the underlying tuning as new render-settings knobs
(`structure.fillDarken`, `borderDarken`, `iconAlpha`, `iconR/G/B`) and
threads them through the structure shader as uniforms, replacing the
previously hardcoded `darken(_, 0.65)` / `darken(_, 0.35)` calls and
the hardcoded white `vec3(1.0)` icon color. The `classicIcons` boolean
in the override schema is the single user-facing knob; the generator
derives the five underlying field values from it. Extends the
ClientGameRunner live-apply path to copy the `structure` slice too,
and adds tests covering the schema and preset derivation.
Adds a single "Name color" toggle (Colored / Black) to the Graphics
Settings modal, backed by a `darkNames` boolean in the override schema
that derives the five underlying name-rendering fields
(fill/outline player-color flags + static outline RGB). Forcing the
outline RGB to 0 in dark mode is what makes the shader's defaultFill
ramp actually render black — flipping the boolean uniforms alone
wasn't enough because the fill is derived from uOutlineColor when
fillUsePlayerColor is false.
Flips the render-settings.json defaults so black names are the
renderer baseline; the modal's no-override state follows the JSON
source of truth. Adds tests covering schema parse behavior and the
generateRenderSettings derivation for each override field.
## Description:
- Add a user-facing **Graphics Settings** modal accessible from the
in-game Settings menu, with live preview as sliders change.
- First two knobs: **Name Scale** and **Minimum Name Size** (the
name-cull threshold).
- Overrides stored as a single JSON blob in `localStorage` under
`settings.graphics`, validated by a Zod schema
(`GraphicsOverridesSchema`). Future graphics knobs just extend the
schema + slider list.
## How it fits together
- `generateRenderSettings(overrides)` (`RenderSettings.ts`) — pure
function: clones `render-settings.json` defaults, layers overrides on
top, returns a fresh `RenderSettings`.
- `UserSettings.graphicsOverrides()` / `setGraphicsOverrides()` —
read/write the blob; falls back to `{}` on a missing/corrupt entry.
- `ClientGameRunner` listens for
`USER_SETTINGS_CHANGED_EVENT:settings.graphics`, regenerates, and
`Object.assign`s each category into the live `view.getSettings()` slice
so passes pick up the new values on the next frame (no renderer
reconstruction).
- Modal reads defaults straight from `render-settings.json` so there's
no duplication.
<img width="599" height="515" alt="Screenshot 2026-05-28 at 11 18 43 AM"
src="https://github.com/user-attachments/assets/263d7d91-10d8-4a66-a069-10015c735d60"
/>
## 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 lil-gui render-settings panel (createDebugGui) has been an orphaned
export since the WebGL renderer landed — no caller, no hotkey, no menu
entry. Wire it to a button in SettingsModal that toggles the panel on
and off, and group it with the existing Performance Overlay toggle
under a new "Development Only" section above the Exit Game block.
## Description:
Labyrinth is a maze type map. My attempt at making a more chess style
board for play. Games with bots appear stable at over 45min average run
times. The map has been setup for team spawn zones for 2, 3, 4, 5, 6,
and 7 teams. Some of the team spawns for odd numbers are experimental
and I would like to see how they play out with live players. Additional
nation names included. There are other design factors like each of the
large squares being within the blast radius of a hydro; small islands
are within the blast radius of nukes.
This is meant as a slower playing game. My intentions are to get some
sort of literal rotation of the map in the future if easily implemented.
That way every time players load the game there would be some
randomization.
As an additional note one of my last edit to the map was the "+" shape
to the islands to allow train passage. Zooming out I can see now that
the pattern is squares and + through out. Did not fully intend on that,
but it felt like good vibes.
https://discord.com/channels/1284581928254701718/1293201128858587207/threads/1497062552784605316https://www.youtube.com/watch?v=e8c-TylT4hshttps://www.youtube.com/watch?v=0-yqrfr3nv0
## 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
PlaysBadly
---------
Co-authored-by: RickD004 <realtacoco@gmail.com>
## Description:
Add map of korean peninsula. Size 1092x2149
Nations: 35
based on provinces
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
DISCORD_USERNAME
crunchybbbbb @crunchybbbbb_59469
<img width="1092" height="2149" alt="Korea-2"
src="https://github.com/user-attachments/assets/874100e8-4a68-4f57-b2f7-49aa87b8194d"
/>
two teams nations war video https://www.youtube.com/watch?v=n4h7GAfAHTM
---------
Co-authored-by: Ricky G.P. <realtacoco@gmail.com>
## Description:
Adds map of the Balkan Peninsula and surroundings. Heavily requested map
with multiple posts on the Discord all with over 10 or 20 upvotes.
23 NPC/Nations based on countries and relevant regions of the area. Adds
an extra 39 nations for crowded Humans vs Nations gamemode for a total
of 62 NPCs, based on regions of multiple countries. Also some flags for
some regions.
Source from NASA DEM, already credited
Photo of base map, and 62 HvN:
<img width="614" height="588" alt="Captura de pantalla 2026-05-24
030105"
src="https://github.com/user-attachments/assets/5742a4c3-1b1f-4ca7-858d-91529861dd81"
/>
<img width="548" height="547" alt="image"
src="https://github.com/user-attachments/assets/758d8ad0-1515-41b8-8d42-14e76cdd54ed"
/>
This map completes the quartet row of "polemic" maps for v32
<img width="678" height="119" alt="image"
src="https://github.com/user-attachments/assets/9e6f4ef1-f0cc-48ea-a59f-b7ff69033b73"
/>
## 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:
Adds Map of the Indian Subcontinent, with indian and pakistani states
and surrounding countries, important rivers like the Ganges, Brahmaputra
and Indus, and Tibet/ theHimalayas
2M land pixels and 52 Nations (i think its fitting that India has the
most nations of a regional map, only continental maps have more)
Should be nice to boost whatever indian playerbase this game might have.
This region also doesnt have any representation aside from continental
maps
<img width="584" height="598" alt="image"
src="https://github.com/user-attachments/assets/4089049a-800b-4e37-ab34-2afc5de821e8"
/>
<img width="418" height="462" alt="image"
src="https://github.com/user-attachments/assets/a68e2424-5972-4105-86c9-0312ab095024"
/>
Elevation data from NASA DEM, already credited in CREDITS.md
No reference test is needed, the test suite automatically iterates over
all GameMapType enum values — no map is hardcoded by name in the tests
## 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:
# Add Friends tab to Account modal
## Summary
- Adds a "Friends" tab to the Account modal, alongside Account / Stats /
Games.
- New `<friends-list>` Lit component covering the full friend lifecycle:
send request, accept / deny incoming, withdraw outgoing, remove friend,
paginated list with "Load more".
- New `FriendsApi.ts` wrapping `GET/POST/DELETE /friends*` endpoints
with typed error codes (`not_found` / `conflict` / `bad_request` /
`request_failed`).
- Zod schemas for the friend API responses in `core/ApiSchemas.ts`.
- Translations under a new `friends.*` block in `en.json`.
Friends and pending requests are displayed by public ID via
`copy-button`, matching the existing clan convention.
## 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:
Adds
<img width="1046" height="901" alt="image"
src="https://github.com/user-attachments/assets/930b0d27-4707-4836-b068-620346e7e3a7"
/>
continuation of infra https://github.com/openfrontio/infra/pull/345
## 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 account modal was getting too large, too much scrolling.
<img width="1091" height="779" alt="Screenshot 2026-05-22 at 2 23 23 PM"
src="https://github.com/user-attachments/assets/9553c80d-7d17-4cfd-8992-88bb335a972e"
/>
<img width="970" height="781" alt="Screenshot 2026-05-22 at 2 23 33 PM"
src="https://github.com/user-attachments/assets/847e70eb-57b7-440b-adb6-bb7c18ada43c"
/>
<img width="1100" height="718" alt="Screenshot 2026-05-22 at 2 23 42 PM"
src="https://github.com/user-attachments/assets/5b08d44c-743a-4245-86a3-bf62e01008e9"
/>
## 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