mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-13 04:18:35 +00:00
7137347b7df4aa0cdccb38a337b9c577c61d052c
18 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7137347b7d |
Fade player names under the cursor, with a graphics setting to tune it (#4221)
## 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 |
||
|
|
9189aac687 |
Improve railroad visibility: own-rail contrast color and thickness setting
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 |
||
|
|
26d8a314ae |
Scale defense-post border + fill rendering to thousands of posts (#4181)
## Description
Scales the defense-post border effect so it works with **thousands** of
Defense Posts instead of silently capping at 64.
### Problem
The border "checkerboard" (drawn on a player's border tiles when a
same-owner Defense Post is within range) was computed per-pixel: for
every border fragment, the shader looped over a `uniform vec4
uDefensePosts[64]` array doing a distance test. Two issues:
- **Hard cap of 64** — posts beyond the first 64 were dropped, so their
checkerboard never appeared.
- **Wrong cost shape** — work was `border_tiles × posts`; every added
post made every border pixel slower.
### Solution: invert the loop into a coverage texture
New `DefenseCoveragePass` stamps one instanced circle per post into a
map-resolution `R8` coverage texture (`1.0` = tile is within range of a
**same-owner** post; the owner check samples `tileTex` at stamp time, so
enemy posts never light up your border). It's a single
`drawArraysInstanced` regardless of post count — the same instancing
pattern `UnitPass`/`StructurePass` already use. The border-stamp shader
now reads one texel of that texture instead of looping; the old uniform
array, the 64-cap, and the per-fragment scan are removed from
`border-compute`/`BorderStampPass`/`BorderScatterPass`.
### Incremental re-stamping (dirty-block grid)
Coverage depends on tile ownership, which drips every frame during
combat, so a full re-stamp every frame would be wasteful at high post
counts. Because a tile changing owner only changes *its own* coverage,
the pass tracks a grid of dirty **blocks** and re-stamps only the blocks
containing changed tiles, scissored to each block (`gl.scissor` confines
the clear + draw to the changed region). Post add/remove and full tile
uploads fall back to a whole-map stamp; so does a frame where most
blocks are dirty. Per-frame cost tracks *how much changed*, not *how
many posts exist*, and scattered fronts (e.g. opposite corners) become
independent small block draws.
### Territory-fill darkening
The coverage texture marks every same-owner in-range tile (interior
included, not just borders), so `TerritoryPass` now also samples it to
darken the territory **fill** around posts. New tunable
`mapOverlay.territoryDefenseDarken` (live-editable in the graphics debug
GUI alongside `defenseCheckerDarken`).
### Performance
Tested with ~1,000 posts blanketing a map — smooth, including on a
low-end (~10-year-old) Chromebook.
## Files
- **New:** `passes/DefenseCoveragePass.ts`,
`shaders/defense-coverage/defense-coverage.{vert,frag}.glsl`
- **Edited:** `Renderer.ts`, `BorderStampPass.ts`,
`BorderComputePass.ts`, `BorderScatterPass.ts`, `TerritoryPass.ts`,
`border-stamp.frag.glsl`, `border-compute.frag.glsl`,
`territory.frag.glsl`, `RenderSettings.ts`, `render-settings.json`,
`debug/Layout.ts`
## Notes
- No user-facing text (no `translateText`/`en.json` changes needed).
- No `src/core` changes — purely client rendering, so no simulation
tests; verified via `tsc`, ESLint, `build-prod`, and in-game.
|
||
|
|
075547b7b6 |
Incremental GPU scatter recompute for tile borders (#4166)
## Description: Incremental GPU border recompute — sequel to #4159. On 10 yo low-end chrome book this increased performance by ~5fps. I'm now able to get 40fps on GWM. `BorderComputePass` previously re-ran its fragment shader over every tile on the map every time any input changed (tile flip, highlight, relation, defense post). Cost was O(mapW × mapH) per invalidation, and tile flips invalidate it ~every render frame in live play. This PR adds `BorderScatterPass`, which runs the same fragment shader but rasterizes only one POINT per dirty tile (plus its 4 cardinal neighbors, to cover the cardinal-neighbor read in the border shader). Cost is O(dirty tiles) regardless of map size or spatial distribution. ### What changed - New `BorderScatterPass` — owns its own FBO, VAO, and instance buffer; shares the border fragment shader with `BorderComputePass` so the two paths can't diverge in output. - `BorderComputePass.draw()` now picks per frame: - **Full recompute** — when `globalDirty` is set by highlight / relation / defense-post changes (those affect tiles across the whole map). - **Scatter** — when only per-tile patches have been queued via `patchTile()`. - `TerritoryPass.flushTileTexture()` now returns `"none" | "full" | "scatter"` instead of `boolean`, so the renderer can pick the right downstream invalidation: - `"full"` → `borderPass.markGlobalDirty()` (full tile upload supersedes per-tile patches). - `"scatter"` → no-op; per-tile patches were already pushed via the wired `borderPatchConsumer` callback during drip drain. - Renderer wires `territoryPass.setBorderPatchConsumer((x, y) => borderPass.patchTile(x, y))` so every per-tile scatter write to `tileTex` also schedules an incremental border recompute for that tile + its neighbors. ### Known limitation Highlight-thicken rings (within `uHighlightThicken` of a changed tile) are NOT incrementally repainted — they'll lag visually until the next full recompute. In practice this is short-lived (the next highlight change or seek triggers a full recompute) and not visible during normal play; the trade is documented in the `BorderScatterPass` header. ## 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: evan |
||
|
|
d1ce199a52 |
Upload tile delta to GPU (#4159)
## Description Reduces the amount of tile data sent to the gpu each tick, roughly ~10fps rate increase on 10 year old chromebook. Two changes to the territory rendering path: ### 1. Split `passEnabled.mapOverlay` into four flags The single `mapOverlay` toggle controlled four unrelated passes (territory fill, border compute, border stamp, trail). Splits it into `territory`, `borderCompute`, `borderStamp`, `trail` so each can be toggled independently in the debug GUI. Pure rename — default behavior is unchanged (all four default to `true`). ### 2. GPU scatter for per-frame tile texture updates Replaces the dirty-row bbox `texSubImage2D` upload in `TerritoryPass` with a new `TileScatterPass` that uploads a small attribute buffer of `(x, y, state)` patches and runs a single `POINTS` draw into an FBO bound to `tileTex`. Each patch rasterizes as a 1×1 point into exactly its target texel. **Why:** the old path's cost scaled with the bounding box of the dirty rows, not the number of changed tiles. In typical play, tile changes are spread across the whole map (multiple players fighting in different regions, scattered trails/fallout), so the bbox covered most of the map's rows and we re-uploaded mostly-unchanged data every frame. The new path is constant cost in patch count regardless of spatial distribution, and no longer scales with map size. The full-upload path (initial load / seek / spawn-phase flush) is unchanged. `fullUploadPending` correctly supersedes any queued scatter patches. ## Please complete the following: - [x] I have added screenshots for all UI updates *(N/A — no UI changes)* - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file *(N/A — no user-facing text)* - [x] I have added relevant tests to the test directory *(renderer code, not covered by unit tests; verified visually)* ## Please put your Discord username so you can be contacted if a bug or regression is found: evan |
||
|
|
431f22ac94 | Always render player name when under the cursor | ||
|
|
f1045a2022 |
Update & refactor dark mode (#4114)
## Description: - The renderer no longer knows what "dark mode" is. `RenderSettings.dayNight.mode` (`"light" | "dark"`) is gone — passes read neutral values (`lighting.ambient: number`, `lighting.enabled: boolean`). - `render-settings.json` holds the light-mode baseline. Dark mode is just another override layer, applied the same way as graphics settings (`darkNames`, `classicIcons`, etc.). - New `src/client/render/gl/RenderOverrides.ts` exposes two in-place mutators with matching shapes: - `applyGraphicsOverrides(settings, overrides)` — replaces the old `generateRenderSettings` - `applyDarkModeOverride(settings, isDark)` - `ClientGameRunner` regenerates the live settings each time the user setting changes via `deepAssign(live, createRenderSettings())` + the override chain. No per-slice copy list, no intermediate object — adding a new override that touches a new section just works. - Renamed `dayNight` → `lighting`; collapsed `nightAmbient`/`dayAmbient` into single `ambient`; renamed `enableLightCompositing` → `enabled`. - Bumped dark-mode ambient from 0.15 → 0.35 so terrain stays readable. <img width="1250" height="846" alt="Screenshot 2026-06-02 at 11 47 28 AM" src="https://github.com/user-attachments/assets/b41e8ffb-6011-4ba0-9e1f-c2a21ff90794" /> ## 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: evan |
||
|
|
2c8a66625c |
Feature/Move theme system from core to client-side ThemeProvider (#4108)
**Add approved & assigned issue number here:** Resolves #2549 ## Description: Themes are purely for the client's rendering, and the server doesn't need context on them. This PR moves `Theme.ts` from `src/core/configuration` to `src/client/theme` and moves affiliation colors to `render-settings.json`. This is to support the ability to add additional themes more quickly, such as colorblind-friendly themes. No visible changes occur from this refactor. ## 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 --------- Co-authored-by: Josh Harris <josh@wickedsick.com> |
||
|
|
475a7ab8af |
bugfix: port construction bar completes early; renderer now reads durations from Config
The renderer kept a parallel CONSTRUCTION_DURATIONS table in src/client/render/GameConstants.ts that had drifted from Config: port showed as 20 ticks but the simulation builds it in 50, so the bar hit 100% and idled for 30 ticks. SAM/silo cooldown constants were also stale (120/75 vs Config's 90/90), making the missile-readiness bar slightly wrong too. Delete GameConstants.ts entirely. Thread the Config instance through WebGLGameView → GPURenderer → BarPass / FxPass / FxSpritePass / WorldTextPass; passes call config.unitInfo(...).constructionDuration, config.SAMCooldown(), config.deletionMarkDuration(), config.msPerTick() directly. Add Config.msPerTick() since no method existed for it. Move the visual-only NUKE_EXPLOSION_RADII (not a game-logic value) into FxSpritePass where it's used. |
||
|
|
aa3959bffe |
feat: territory png based skins (#4006)
## Description: Add image-based territory skins as a new cosmetic type, rendered alongside the existing 1-bit patterns. Skins render a single PNG centered on each player's spawn tile — opaque pixels show the skin (multiplied by team color in team games, raw colors in FFA), transparent pixels and tiles outside the image bounds fall through to the regular player palette color. **Cosmetic plumbing** - `SkinSchema` in `CosmeticSchemas.ts`, optional `skins` map on `CosmeticsSchema` - `PlayerSkin`, `PlayerCosmetics.skin`, `PlayerCosmeticRefs.skinName` in `Schemas.ts` - Server-side resolution: `PrivilegeCheckerImpl.isSkinAllowed` (gated by `skin:*` / `skin:<name>` flares) - Client persistence: stored under `PATTERN_KEY` (`pattern:` and `skin:` share one slot — they're mutually exclusive) - `getPlayerCosmeticsRefs` only emits a `skinName` when cosmetics are loaded, the skin exists in the catalog, and the user has the right flare — otherwise drops the ref and clears storage **Renderer** - `SkinAtlasArray` — fixed `TEXTURE_2D_ARRAY`, 1024×1024 per layer, exact layer count allocated once at game start from the locked-in player set. No resize, no callbacks, no retained `HTMLImageElement`. Zero GPU cost when no players have skins (1×1 placeholder). - `skinLayerTex` (R8UI 4096×1) — per-player `layer + 1` (`0` = no skin) - `skinAnchorTex` (RG16UI 4096×1) — per-player spawn tile, so the PNG center anchors at each player's spawn (re-uploads when the player re-picks during spawn phase) - `WebGLFrameBuilder.syncPlayers` collects unique skin URLs on first sync and calls `view.initSkinAtlas(urls)` once; `clearCaches()` resets so seek/replay re-initializes - `territory.frag.glsl`: skin branch is mutually exclusive with patterns; bounds-checks UVs against `[0, 1]` so the image is a single stamp, not tiled; alpha-blends against the player palette color so transparent pixels and out-of-bounds tiles render as the regular player color **Hover highlight (global UX change, not skin-scoped)** - Existing hover highlight changed from "brighten toward white" to "saturation boost." Applies to all players regardless of skin/pattern/flat-color — looks better across the board. **UI** - `CosmeticButton` renders skins as a single `<img>` (object-contain) - `TerritoryPatternsModal` merges patterns + skins into one grid; single "default" tile clears both - Selecting a pattern clears the skin and vice versa (mutually exclusive) - `Store` pattern tab includes skin entries (purchasable, not-yet-owned) - `PatternInput` lobby button previews the active skin when one is set **Memory** - 0 skin players → ~4 bytes (placeholder) + ~40 KB fixed per-player tables - 1 skin player → ~5.6 MB GPU - 5 skin players → ~28 MB GPU - 10 skin players → ~56 MB GPU **Tests** - `tests/Privilege.test.ts`: 13 new cases covering `isSkinAllowed` (wildcard, exact-match, missing flare, missing skin, forged refs) and `isAllowed` integration (allowed/forbidden paths, short-circuit when invalid skin is paired with valid other cosmetics) ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [ ] 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 |
||
|
|
b4a14f9b9d |
Move attack troop overlay to WebGL (#3996)
## Description: Replaces the DOM-based `AttackingTroopsOverlay` with `AttackingTroopsController`, rendering attack troop counts through `WorldTextPass` instead of a separate fixed-position DOM container. ## Summary - New `AttackingTroopsController` polls `attackClusteredPositions()` every 200ms and pushes labels to the WebGL view each frame, lerping cluster positions over 250ms for smooth front-line movement (replaces the old CSS `transform 0.25s` transition). - `WorldTextPass` gains `setAttackTroopLabels()` and renders them at a fixed on-screen size (zoom-independent) using `screenScale / zoom`. - World text now draws on top of `NamePass` so attack callouts aren't hidden behind centered player names. - Fragment shader adds a soft quadratic dark halo around every world-text label; extent uses the remaining SDF range after the hard outline so it fades smoothly to zero (no rectangular clipping). - Deletes `AttackingTroopsOverlay.ts`; existing unit tests repointed to the controller's exported `alignClusterOrder`. <img width="369" height="395" alt="Screenshot 2026-05-24 at 4 43 51 PM" src="https://github.com/user-attachments/assets/4dbffe20-77f9-4c0f-b956-ecf543538f8d" /> ## 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 |
||
|
|
b486caa6f4 |
Wire view-mode toggles (alt-view + coordinate grid) via new ViewModeController
Moves the AlternateViewEvent / ToggleCoordinateGridEvent subscriptions out of ClientGameRunner into a dedicated controller in src/client/controllers/. Also wires ToggleCoordinateGridEvent (M keybind) — previously emitted with no listener — so the persistent coordinate-grid toggle works. Grid + alt-view hide names only under alt-view; M keeps names visible. |
||
|
|
ee04a19d3c |
unit price (#3989)
## Description: # Ghost structure cost label Renders the gold cost of the currently-selected build under the ghost structure cursor, with color-coded affordability/placement state. Honors the existing `cursorCostLabel` user setting (legacy name `ghostPricePill`, already shipping ON by default). ## Behavior | State | Color | |---|---| | Can afford + valid placement | white | | Can afford + can't place here (port on land, overlap, …) | gray | | Can't afford | red | The number is formatted via `renderNumber` (project-wide convention — `1.5K`, `1.23M`, etc.) and rendered as MSDF text at a fixed world-space scale, centered under the ghost icon. ## Implementation The cost was already plumbed end-to-end on [`GhostPreviewData.cost`](src/client/render/types/Renderer.ts) but never visualized. This PR: - Extends [`GhostPreviewData`](src/client/render/types/Renderer.ts) with `showCost` (from setting) and `canAfford` (gold vs. cost check, computed in [BuildPreviewController](src/client/controllers/BuildPreviewController.ts)). - Adds a `setGhostCostLabel(...)` channel to the MSDF text pass — one persistent, non-animated text instance alongside the existing ephemeral popups. No new pass, no new shader. - Wires [`Renderer.updateGhostPreview`](src/client/render/gl/Renderer.ts) to push the label whenever a ghost is active. - Renames `ConquestPopupPass` → [`WorldTextPass`](src/client/render/gl/passes/WorldTextPass.ts) (and its shader dir `conquest-popup/` → `world-text/`) since it now handles conquest popups, bonus popups, and the ghost cost label. Done with `git mv` so history is preserved. https://github.com/user-attachments/assets/c5b21bf3-f440-4c28-9b94-843df9bf6a37 ## 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 |
||
|
|
fe6581e3fe |
update webgl nuke effects (#3984)
## Description: Reworks the visual look of nuked tiles to read uniformly green (no more brown/black bleed-through), and moves the ember "particle" effect out of the border passes — where it lived as a storage-sharing hack — into the fallout system where it belongs. ## What changed visually - **Fresh fallout**: bright uniform bloom with a hint of flickering green particles dampened on fresh tiles, ramping up as heat decays (`particleFreshScale` controls the fresh-tile dampening). - **Stale fallout**: dark-green ground (was near-black charcoal), with full-strength flickering particles in dark-green ↔ light-green. - **Particles**: per-tile flicker is now de-synced (each tile pulses at its own rate, 0.4×–1.6× base speed) so the eye can't lock onto a global rhythm. - **No more brown/black pixels** in fallout zones. Two root causes were fixed: - The territory pass now renders stale-nuke ground for **all** fallout tiles, not just unowned ones — so an owned player's color can't show through where the bloom is dim/transparent. - The ember stamp (which fully replaced tile color with orange) is gone; particle render is now additive and color-tuned green. ## Architecture cleanup The ember effect was conceptually fallout-domain, but lived in `BorderComputePass` (writing intensity into `borderTex.g`) and `BorderStampPass` (stamping orange dots), just because the border pass already had an RGBA8 texture with a free G channel. Two consumers read from it (`BorderStampPass`, `FalloutLightPass`), and the per-tile flicker math used no border data at all. This PR relocates the math inline into the two passes that actually need it (`FalloutBloomPass.extract.frag.glsl` and `FalloutLightPass.fallout-light.frag.glsl`), drops the ember code from both border passes, and renames `mapOverlay.ember*` → `falloutBloom.particle*` so the settings live with their pass. Side benefits: - **Animation correctness**: the old setup only updated ember intensity when `BorderComputePass`'s dirty flag flipped (highlight change, relations update, etc.), so the supposed flicker was actually a frozen snapshot between border events. The new inline path runs every frame as intended. - **Slightly cheaper per-frame compute**: removed a per-dirty-event full-map writeback to `borderTex.g`; added a few cheap ALU ops (1 sin + 2 hashes) per fallout tile in shaders that were already running. Same texture memory. ## Other small changes - Renamed `mapOverlay.charcoal*` → `mapOverlay.staleNuke*` (charcoal was a misnomer now that the ground is green). - Added `staleNukeR/G/B` for the ground color (was hardcoded grey). - `intensityHot` bumped 0.6 → 1.8 for a brighter fresh-nuke glow. - Raised `railroad.railMinZoom` 2 → 4 and `railDetailZoom` 4 → 6 so rails pop in later (separate small commit). <img width="354" height="371" alt="Screenshot 2026-05-22 at 10 37 34 AM" src="https://github.com/user-attachments/assets/03b46c45-c617-41b3-b3e4-9934f064bfe1" /> <img width="335" height="358" alt="Screenshot 2026-05-22 at 10 37 43 AM" src="https://github.com/user-attachments/assets/af370b19-8f22-4694-9859-1ad52aa755a7" /> <img width="651" height="613" alt="Screenshot 2026-05-22 at 10 38 09 AM" src="https://github.com/user-attachments/assets/e06e5101-8529-49f6-b29a-ce0563eb52d6" /> ## 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 |
||
|
|
c82b078dab |
Stagger territory tile rendering across frames (#3973)
relates to #893 ## Description: Territory updates were uploaded in one shot per game tick, producing a 10 Hz tile update which looked choppy. This change drips each tick's tile changes across the ~6 render frames between ticks so the fill flows continuously instead of stepping. Inside TerritoryPass, each changed tile is hashed by ref into one of N buckets (configurable via tileDrip.bucketCount, set to 9 — gives ~50 ms of jitter headroom over the tick period without making attacks feel laggy). One bucket drains per render frame. The stable per-ref hash keeps repeated updates to the same tile in arrival order, so the latest owner always wins. While in there, moved trail state ownership out of TerritoryPass and into TrailPass where it belongs — the territory shader doesn't sample trailTex, so the colocation was just code-reuse drift. ## 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 |
||
|
|
ed928db081 |
Display territory skins again (#3966)
## Description: Display territory skins (patterns) again. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: tryout33 |
||
|
|
1dd00f6264 |
push terrain deltas to the WebGL view so water nukes show
Terrain was uploaded once at game start and treated as static — water nukes (land → water conversion) mutated the sim's terrain bytes but the rendered terrain stayed dry. Plumbed a delta path: TerrainPass and RailroadPass each get applyTerrainDelta(refs, bytes), Renderer + GameView forward, and WebGLFrameBuilder pushes each tick from gameView.recentlyUpdatedTerrainTiles(). Per-tile encoding is shared via the new encodeTerrainTile helper in ColorUtils so the startup full-map build and the per-tile delta updates can't drift. |
||
|
|
4cd22a9b5c |
rename render/ files to UpperCamelCase to match client convention
The render/ tree was the only place in the client still using kebab-case filenames. Brings ~80 files in line with the rest of src/client/ (BuildPreviewController, TransformHandler, etc.). Directories kept as they were (name-pass/, fx-pass/, passes/, utils/, debug/) since the codebase already mixes those. Two collisions surfaced and got resolved: render/types/ is a directory, not a file, so its imports kept the lowercase form; and the sed pass incidentally normalized core/pathfinding imports, which had to be reverted since that file is actually lowercase on disk despite some imports having referenced it as ./Types under macOS case-insensitive resolution. |