Period: November 1, 2025 Total Commits: 18
Hey, here’s what we’ve been working on today. The big themes: getting procedurally generated maps loading correctly for everyone, fixing a few critical multiplayer desync and rendering issues, and making the renderer fast enough to actually enjoy it. There’s also some lobby and campaign HUD cleanup that should feel nicer right away.
What’s New
-
Procedural multiplayer maps, properly integrated
- We now feed server-generated maps through the same campaign map loader the game already trusts. That means correct dimensions, castles, roads, and spawn areas without special-case code.
- Spawn zones now come from the server and scale with map size instead of being hardcoded.
- The main “objective” castle is included and clearly tagged in the data, so matches are actually winnable and the castle count matches your settings.
- Result: maps look like they should, and all systems (pathfinding, rendering, UI) sync up automatically.
[screenshot: procedurally generated map with roads and main castle at 2c35a40]
-
Random map generation you can feel
- Seeded generation with configurable map sizes and placement styles:
- Sizes: Tiny (11x9), Small (19x11), Medium (23x13), Large (27x15), VeryLarge (31x17)
- Mazing: None, Light, Heavy
- Castle positioning: Edges, Corners, Scattered
- These settings are part of the lobby flow and broadcast to everyone, so what you pick is what you play.
- Seeded generation with configurable map sizes and placement styles:
-
Campaign mode HUD cleanup
- Minimal HUD for campaign with a compact wave timer and next-wave preview.
- Endless preview uses your existing spawn points so planning is easier at a glance.
[screenshot: compact campaign HUD with wave preview at 29e9273]
-
Lobby layout improvements
- More space for settings, scrollable panel when needed, clearer Start/Ready area, and a tooltip explaining why Start is disabled when it is.
- Settings changes are centralized and visible to all players; only the host can modify them.
[screenshot: updated lobby settings panel and start buttons at 01caceb]
What Got Fixed
-
Map data actually reaches clients
- The server now includes map data when sending state. Previously it generated maps but didn’t serialize them, so clients saw the default grid. That’s fixed.
-
Late joiners see the correct map
- We apply map data the first time we receive it, not just on tick 0. Reconnect mid-match and you’ll still get the right terrain, roads, spawn areas, and castles.
-
Castles in the right places for both teams
- No more mirroring logic—each team sees its own board with the same castle coordinates. This removes weird mismatches and duplicate castles.
- Renderer now re-initializes after map data is applied so it reads the correct dimensions before setting up the grid and castles.
-
Main castle restored
- We stopped filtering out the main castle from generated maps. It’s now included and flagged, so your final push has a real target.
-
Desync fix for full lobbies
- Players rejected from full lobbies were briefly getting tick updates. That created false desyncs without proper state. We moved validation earlier and block them from receiving any game state.
-
Crash and flicker issues
- Squashed a null material crash on grass tiles that occasionally broke rendering.
- Fixed an order-of-operations issue that could delete resources before the renderer was done with them.
- Stopped a scene-graph thrash where castle meshes were being removed and re-added every frame.
Under the Hood
-
Big renderer wins (and smoother battles)
- Grass tiles are now drawn with instanced rendering instead of hundreds of separate meshes.
- Frustum culling is disabled across the board since the camera never moves. Those checks were pure overhead.
- Materials are shared instead of created per-tile or per-icon, cutting shader program switches dramatically.
- Together, these changes take us from ~20–40 FPS to much closer to 60 FPS in typical matches on a 29x15 grid.
[screenshot: smooth 60 FPS battle on medium map at ee32d73]
-
Unified team representation
- We switched from string team IDs to a numeric enum across server, client, maps, and editor. That removed a class of mismatches (like Team A castles not showing).
- For older maps, the validator auto-converts legacy team values so your files still load without edits.
-
Cleaner map pipeline
- Multiplayer now uses the same campaign map system for dimensions, roads, spawn areas, and castles. One code path, fewer edge cases, more consistent behavior.
- Added a debug visibility panel for development builds to quickly toggle entities and verify what’s on-screen.
-
Profiling and stability
- Added scene stats logging to help track object counts and spot performance regressions.
- Cut out render-list rebuilds by keeping castle meshes alive and updating them in place instead of re-adding them every frame.
Thanks to everyone who reported the castle placement weirdness and the “default map after reconnect” issue—those were key in tracking down the timing bugs. If you notice any remaining hitching or oddities on VeryLarge maps, let us know what you’re running and what you saw. It’s getting there.