RPG Project

December 2025 – present

An open-world RPG inspired by Kenshi, EverQuest, and Factorio. 32km × 32km seamless world, ML-generated terrain, and a clean separation between simulation and rendering that could eventually support headless servers.

  • ML Terrain - Stable Diffusion + LoRA trained on real heightmaps, edge-conditioned for seamless tiling
  • Rust Core - 13k lines handling world grid, entity management, ONNX inference, terrain processing
  • Godot Client - 12k lines of pure rendering, no simulation logic in the node tree
  • Chunk Streaming - 512m chunks, LOD system for vegetation, handles the 32km scale
RPG Project Architecture
Godot handles rendering, Rust handles simulation - clean split for future server extraction

The Split

GDScript is fine for game logic, but not for iterating over millions of cells or running ML inference. Everything performance-critical lives in Rust via GDExtension: the 4096×4096 world grid (16 million cells), entity management with spatial indexing, biome assignment, terrain post-processing, and ONNX inference for the diffusion model.

The Godot side is pure rendering - camera control, terrain visualization (Terrain3D addon), entity visuals, atmosphere effects. No game state lives in the node tree. This simulation-client split means I could eventually extract the Rust layer into a headless server without rewriting the game logic.

Terrain Generation

Terrain Generation Pipeline
From diffusion model training to final biome assignment

The terrain system is the most interesting part. I fine-tuned Stable Diffusion 1.5 with LoRA on real-world heightmap data (GEBCO, SRTM). The model learns to generate realistic terrain patterns - mountain ranges, coastlines, valleys - not just noise.

The trick for a seamless 32km world is edge conditioning. Each tile is generated with 9 input channels: 4 for the noisy latent, 4 for neighboring tile edges, and 1 mask. The model learns to continue terrain features across tile boundaries. Post-processing adds thermal and hydraulic erosion for natural-looking results.

Five continental themes (heartland, frozen_north, sunlands, ashlands, archipelago) each have their own text embedding, so the same pipeline produces dramatically different worlds.

World Scale

32,000m × 32,000m playable area. 4096×4096 grid cells at ~8m resolution. 900m peak elevation. ~35% water coverage. 22 biome types assigned per-cell based on elevation, slope, and theme. Chunk-based streaming loads 5×5 chunks (2.5km radius) around the camera, with LOD transitions for vegetation (full mesh → multimesh batching → billboards).

Entity System

Entities tick in Rust with a behavior state machine: Idle, Wandering, Moving, Following, Combat, Fleeing, Dead, Scripted. Spatial indexing by chunk keeps updates fast - only entities in loaded chunks get full simulation, others run simplified logic. The Godot side just syncs visuals to whatever Rust reports.

World modifications (cut trees, mined ore, placed structures) use delta storage - only deviations from the procedural baseline get persisted. Respawn timers are configurable per object type (trees: 7 days, bushes: 6 hours, rocks: never).

Under the Hood

  • Rust: WorldGrid, EntityManager, BiomeSystem, StateManager, ONNX inference, erosion algorithms
  • Godot: CameraRig (RTS/FP/planet modes), TerrainManager, ForestSpawner, EntitySpawner, atmosphere shaders
  • Python: LoRA training pipeline, ONNX export, real terrain data processing
  • Rendering: Terrain3D, volumetric clouds, god rays, Gerstner wave water shader

Stack: Godot 4.5, Rust (godot-rs), Python (PyTorch, Diffusers), ONNX Runtime

This is my “learn game dev properly” project. Will it ship? Unknown. But I’ve learned a ton about procedural generation, simulation architecture, and the real cost of the GDScript performance boundary.