Skip to content

perf: stop rebuilding map source per frame, fix stale initial centre, prefetch at login - #745

Merged
gaidheal1 merged 2 commits into
developmentfrom
perf/map-animation-and-initial-centre
Aug 10, 2026
Merged

perf: stop rebuilding map source per frame, fix stale initial centre, prefetch at login#745
gaidheal1 merged 2 commits into
developmentfrom
perf/map-animation-and-initial-centre

Conversation

@gaidheal1

Copy link
Copy Markdown
Member

Summary

  • Stop rebuilding the entire MapLibre GeoJSON source on every animation frame — only the moving pieces (characters/journeys) update per frame now, static features (buildings, roads, subzones) are set once per viewport fetch instead of every frame.
  • Fix the map's initial camera logic: it used to pick an arbitrary "first population centre" rather than the player's own village. Added a new InitialMapCentreView backend endpoint that returns the requesting player's linked character's village (falling back to a deterministic default if unlinked), and wired the frontend's useInitialMapCentre onto it.
  • Prefetch the map's two cheap, one-shot queries (/map/initial-centre/, /map/world-bounds/) as soon as fetch_info resolves at login, instead of only firing them once the player navigates to the map page — so MapPage can skip a network round-trip on mount. Deliberately does not prefetch /map/viewport/, since that needs a bbox only the mounted map component can produce and starts a 2s poll once enabled.

Testing

  • Frontend: typecheck (tsc --noEmit) and lint (eslint) clean; vitest suite run by the user, all passing.
  • Backend: user-run test suite, all passing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01C6BX7dFJWn2xMYn9qggdos

gaidheal1 and others added 2 commits August 10, 2026 00:40
…entre

Map.tsx's walker animation loop rebuilt the entire GeoJSON source
(buildings/roads/fields/boundaries) every 16ms even though only
character positions change per frame. Split buildVillageSourceData into
buildStaticVillageFeatures (memoized, rebuilt only when features change)
and buildCharacterPointFeatures (per-frame). The animation loop is now
also gated on there actually being walking characters, instead of
running unconditionally.

Separately, useMap.ts's initial-camera logic assumed a single seeded
village and picked "the first population centre" from the full
population-centres list, which is now stale with multiple villages
imported from locations/data/. Added a lightweight
InitialMapCentreView (/map/initial-centre/) that returns just enough
(id/name/bbox) to frame the camera, preferring the population centre of
the requesting player's actively linked character
(Player.active_link) and falling back to the lowest-pk centre
otherwise. Frontend now fetches this cheaply before the bbox-scoped
viewport poll takes over as the source of truth.

Backend: locations/tests/test_initial_map_centre_view.py (3 tests).
Frontend: MapPage.test.tsx updated for the new fetchInitialMapCentre
mock; also fixed a flaky prefetch effect that used a dynamic import()
for fetchPopulationCentreMap, which could race and skip the vi.mock
when prefetching two different villages concurrently - now a normal
static import.
GameContext now primes useInitialMapCentre's and useMapWorldBounds's
query cache entries as soon as fetch_info resolves, instead of only
firing them once the player navigates to the map page. Both are
cheap, one-shot fetches, so warming them at login lets MapPage skip a
network round-trip on mount for players who go on to open it.

Extracted the {queryKey, queryFn, staleTime, gcTime} for each into
exported query-option objects in useMap.ts, reused by both the hooks
and GameContext's prefetch, so the two can't drift onto different
cache keys.

Deliberately doesn't prefetch /map/viewport/: it needs a bbox only the
mounted map component can produce, and starts a 2s poll once enabled -
prefetching it at login would poll map data in the background for
every session regardless of whether the player ever opens the map.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C6BX7dFJWn2xMYn9qggdos
@gaidheal1
gaidheal1 merged commit 4317385 into development Aug 10, 2026
2 checks passed
@gaidheal1
gaidheal1 deleted the perf/map-animation-and-initial-centre branch August 10, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant