Hey everyone, Mister Phil here with another devlog update!
Today marks a major milestone for Stellar Throne, my sci-fi 4X strategy game. For those just joining: Stellar Throne runs on a dual-engine architecture, using Godot for the UI client and Zig for the high-performance simulation backend.
Yesterday’s work was all about one huge goal — finally enabling the Zig simulation backend in production and fixing the critical serialization bugs that had been blocking deployment for days.
🧩 The Context: A Fully Functional Engine That Couldn’t Run
At the start of the day, I had a complete Zig simulation engine — all tests passing, a 52× performance improvement validated, and everything ready to go.
Except… I couldn’t actually use it.
The bridge between Godot and Zig — serialization — was broken. The game state couldn’t properly flow between the two, leaving the new engine stranded behind a wall of data mismatches.
⚙️ Fixing the Turn Processing Hang
The first issue was a classic async race condition. The game was using await to wait for a “turn completed” signal, but the listener was being connected after the signal was emitted.
Result: the code waited forever for an event that had already happened.
Fix: I stored the signal reference before calling the turn coordination function. That ensured the listener was ready before any signals could fire. I also added yield calls in the turn sequencer to give the engine a frame to process signals between phases.
✅ Result: Turn processing is now stable and reliable.
🔄 The Real Challenge: Serialization Across Engines
The real battle was with serialization mismatches.
Godot properties used snake_case (star_system_id, fleet_name), while Zig structs used camelCase (starSystemId, fleetName). Every deserialization failed because of these naming conflicts.
I added manual field mapping in Zig — tedious, error-prone, and partial. Empires loaded correctly, but fleets, planets, and star systems still broke.
The breakthrough.
I implemented bidirectional camelCase serialization across all four major data structures:
SimEmpireSimFleetSimPlanetSimStarSystem
Each gained custom toJSON() and fromJSON() methods that output camelCase and accept both camelCase and snake_case.
| Struct | Lines Added |
|---|---|
| SimEmpire | +210 |
| SimFleet | +274 |
| SimPlanet | +44 |
| SimStarSystem | +131 |
All test fixtures were also updated to camelCase, covering five scenarios:
Edge Case Deficit
Edge Case Empty Empire
Fleet Upkeep
Single Turn Minimal
Ten Turn Economy
🧠 Type System Fixes & Data Integrity
Once serialization worked, I enabled the Zig backend in production. Immediately, Godot’s type system rebelled.
Files like Building.gd, Empire.gd, and Fleet.gd had overly strict type annotations that didn’t match the Zig output. I went through each file and refined type declarations to handle the new data correctly.
Then came the fleet disappearance bug — fleets vanished after turn processing. Turns out:
The
locationfield was structured incorrectly.fleet_namesometimes wasn’t serialized at all.
Both fixed.
And finally, empire colors were lost during serialization. The culprit?
Godot’s Color type can appear as RGB, RGBA, hex, or even name strings. Zig wasn’t handling that variety.
Solution: standardize on RGBA objects — {r, g, b, a} — for full round-trip fidelity between engines.
📈 The Numbers
| Category | Changes |
|---|---|
| Zig serialization | +659 lines |
| GDScript type fixes | 6 files, +41 lines |
| Fleet & color bug fixes | +89 lines across 5 files |
| Test framework | +150 lines new assertions |
| Test fixtures | +59 lines camelCase JSON |
8 commits in total.
The Zig backend is now fully active in production.
Game state round-trips cleanly. Colors, fleets, and names all persist. Integration tests are green across the board.
⚡ The Results
The game now runs 52× faster with the Zig simulation engine enabled by default.
Large galaxies that once took seconds now resolve in milliseconds. The performance leap is live — and dramatic.
🧭 Next Steps
Monitor gameplay for any hidden serialization edge cases
Expand integration test coverage
Begin profiling the Zig engine for further optimization
That’s the devlog update!
Thanks for following along as Stellar Throne crosses another huge milestone.
👉 Visit mrphilgames.com for more updates, devlogs, and behind-the-scenes deep dives.