Skip to content

Architecture

Component Technology
Language Rust
Game engine Bevy 0.18 (ECS)
Physics Avian2D
Serialization serde + serde_json, RON
Noise noise crate (Perlin FBM)
CLI clap (derive)

Systems run in a defined order via GameSet:

Input → Commands → Movement → Fov → Lighting → Barriers → Render
Set Responsibility
Input Keyboard, mouse, controller input
Commands TCP server commands, overseer actions
Movement Player/unit movement, stairs, terrain sync
Fov Shadowcasting field of view computation
Lighting Light source propagation
Barriers Elevation barrier updates
Render Tile sprite rendering

Dependencies: Movement runs after Input. Fov runs after Movement. Lighting and Barriers run after Fov. Render runs last.

WorldMap
└─ HashMap<i32, Layer> z-level → Layer
└─ HashMap<IVec2, Chunk> chunk pos → Chunk (32×32)
├─ Vec<BlockVolume> dense block storage
├─ HashMap<(u8,u8), FloorCoverId> sparse floor covers
└─ HashMap<(u8,u8), CeilingCoverId> sparse ceiling covers
Constant Value
CHUNK_SIZE 32×32 tiles
TILE_SIZE_PX 32.0 pixels
Z range -100 to +100
  • X = East (+) / West (-)
  • Y = North (+) / South (-)
  • Z = Vertical levels (up +)
  • Player at z=N stands on a solid block at z=N-1

BlockType is a u16 newtype (not an enum) for extensibility — supports up to 65,535 block types.

BlockRegistry uses a flat Vec<Option<BlockProps>> indexed by the u16 ID for O(1) lookup. Block properties include:

  • blocks_movement — whether the block blocks horizontal movement
  • supports_standing — whether units can stand on it
  • vision_transmittance — FOV light pass-through (0.0–1.0)
  • light_transmittance — lighting pass-through (0.0–1.0)
  • placeable, mineable — interaction rules
  • Sprite atlas coordinates and color fallback

Block and item definitions live in RON files, loaded at startup:

  • assets/blocks.ron — block types, properties, sprite mappings
  • assets/items.ron — item definitions (id, name, group, stack size)

Atlases: Natural.png (20×22 grid), Civilized.png (24×18 grid), People.png.

No recompilation needed to add or modify blocks and items.

A DirtyFlags resource tracks what needs recomputation:

  • render_dirty — tile sprites need refresh
  • lighting_dirty — light values changed
  • fov_dirty — visibility needs recalculation
  • barriers_dirty — elevation barriers changed
  • chunks_generated — new chunks were created

Systems check dirty flags and skip work when nothing changed.

GameCommand is a serde-tagged enum routed through a CommandQueue. Commands come from:

  • TCP server (kinswardctl)
  • Overseer mode UI
  • Internal game systems

The command executor processes the queue each frame in the Commands system set.

A global TaskQueue holds Build, Demolish, and Pickup tasks. Tasks are created by overseer commands or zone operations. Idle Colony units automatically pick the nearest pending task.

InputMode tracks the current game mode:

  • Adventure — direct player control
  • Overseer — RTS-style unit management

Mode switching triggers camera transitions and input handler swaps.

  • UiTheme — centralized dark-theme configuration (50+ color/size constants) applied across all panels
  • InputRegistry — replaces scattered input handling with 21 registered bindings across 5 contexts (Global, Adventure, Overseer, InventoryOpen, MapView); enables context-aware control hints
  • UiAnimator — panel transition animations (Fade, SlideUp, SlideUpHigh, SlideDown, SlideLeft, SlideRight) for floating panels
  • Scrollbar — vendored bevy_scrollbar 0.6.0 for mouse-wheel scrolling with visual thumb. Pattern: scrollable node + Scrollbar sibling in Row wrapper
  • Hover effectsCardBaseColor + Hovered component (CSS-like, includes descendants) for card hover feedback. ButtonBaseColor + Button for toolbar buttons. Both use Hovered from bevy_picking
  • UiHovered — centralized resource (src/ui/picking.rs) checking hover from HoverMap filtered by Node. Replaces all PickingInteraction queries
  • Observer clicks — all UI clicks use On<Pointer<Click>> observers with event.propagate(false). Legacy Interaction polling fully removed
  • UI picking — panels use direct PositionType::Absolute positioning (no fullscreen wrapper overlays). Sprite/mesh picking disabled via require_markers: true. Non-interactive child nodes use Pickable::IGNORE
  • UiSlotManager — centralized panel management system

SystemTimings resource tracks per-system execution times. Accessible via the QueryPerf TCP command and kinswardctl perf.

Maps (x, y) columns to walkable z-levels. Used by pathfinding and grounding to determine where units can stand. Rebuilt when blocks change.

Tile-based rendering: one Bevy entity per visible tile. Sprites come from 10px-cell texture atlases scaled 3.2× to fill the 32px tile size. 2D bloom (intensity 0.2) is applied to the camera.

Performance optimizations:

  • Rendered State Matrix — fingerprint-based diffing skips ~98% of unchanged tiles each frame
  • Entity pooling — tile entities are recycled instead of spawned/despawned
  • FOV viewport culling — shadowcast computation skipped for observers outside the viewport
  • Lighting viewport culling — XY culling for emitters in light propagation
  • Incremental FOV merge — refcounted visibility replaces full clear-and-rebuild

Final tile color formula:

color = base_color × depth_factor × light_value × visibility
Module Responsibility
src/core/ Game phase state machine, system scheduling (GameSet), input registry, diagnostics timing
src/world/ WorldMap, blocks, chunks, layers, surfaces, grounding
src/commands/ GameCommand, executor, TCP server, region-map export
src/render/ Viewport, sprites, FPS display
src/fov/ Shadowcasting FOV, visibility maps, refcounted multi-observer
src/lighting/ Light propagation with viewport culling
src/generation/ Procedural generation, climate pipeline (16 modules)
src/inventory/ Items, block-item mapping, inventory UI, hotbar
src/interaction/ Block mining/placing, pickup/drop, world items
src/movement/ Player entity/movement, movement rules, elevation barriers, proximity, physics
src/units/ Unit components (Race, Faction, UnitTraits), spawner, possession, movement
src/names/ Name generation: NameGenerator, UnitName, WorldName, syllable tables
src/overseer/ RTS mode: camera, selection, commands, pathfinding, tasks
src/companions/ Companion behaviors
src/ui/ UI system — UiTheme, InputRegistry, UiAnimator, floating panels
Binary Purpose
kinsward Main game
kinswardctl CLI debug tool
worldgen Headless world generation