Skip to main content

Overview

The terrain system generates procedural 3D terrain using Perlin noise with support for flat zones under stations and buildings. Location: packages/shared/src/systems/shared/world/TerrainSystem.ts

Terrain Configuration

World Specs

Noise Layers

Terrain height is generated from multiple Perlin noise layers: Combined height is normalized to [0, 1] then scaled by MAX_HEIGHT.

Flat Zone System

Purpose

Flat zones create level ground under stations (banks, furnaces, anvils) for professional world building. Without flattening, stations would sit on bumpy terrain at odd angles.

Configuration

Flat zones are defined in station manifests (stations.json):

How It Works

1. Flat Zone Registration

When a station spawns, TerrainSystem registers a flat zone:
Dimensions calculated from:
  • Station footprint (from model bounds)
  • flattenPadding (extra space around footprint)
  • flattenBlendRadius (smooth transition zone)
Height sampled from:
  • Procedural terrain at station center
  • Ensures flat zone matches surrounding terrain elevation

2. Spatial Indexing

Flat zones are indexed by terrain tiles (100m) for O(1) lookup:

3. Height Calculation

When terrain height is requested, flat zones are checked first:

4. Smooth Blending

Flat zones use smoothstep interpolation for natural transitions:

API Methods

Station Manifest Integration

StationDataProvider

Location: packages/shared/src/data/StationDataProvider.ts Loads station configurations including flat zone settings:

Automatic Flat Zone Creation

When StationSpawnerSystem spawns a station:
  1. Check if flattenGround: true in station manifest
  2. Get station footprint from model bounds
  3. Calculate flat zone dimensions (footprint + padding)
  4. Sample terrain height at station center
  5. Register flat zone with TerrainSystem
  6. Terrain mesh updates automatically

Example Station Config

This creates:
  • Flat zone centered on bank position
  • Width/depth = bank footprint + 1m (0.5m padding on each side)
  • 1m blend radius for smooth transition
  • Height = procedural terrain at bank center

Performance

Spatial Index Efficiency

  • Lookup: O(1) via terrain tile key
  • Memory: Only stores zones, not per-vertex data
  • Updates: Flat zones registered once at startup
  • Runtime: Zero allocations in height lookup hot path

Terrain Tile Caching

  • Terrain tiles (100m) cached after generation
  • Flat zones don’t invalidate cache
  • Height lookups check flat zones before cache

Biome Integration

Flat zones work with all biome types:
  • Grasslands: Flat zones blend with gentle hills
  • Forests: Stations clear vegetation in flat area
  • Mountains: Flat zones create plateaus on slopes
  • Deserts: Flat zones blend with dunes

Debugging

Console Logging

TerrainSystem logs flat zone activity:

Visual Debugging

Flat zones are visible in-game:
  • Bumpy terrain contrasts with flat station areas
  • Smooth blend transitions prevent sharp edges
  • Stations sit level on ground

Future Enhancements

Potential improvements for dynamic flat zones:
  • Player-Placed Structures: Flatten ground under player buildings
  • Dynamic Registration: Add/remove flat zones at runtime
  • Circular Zones: Support circular flat areas (not just rectangular)
  • Height Adjustment: Raise/lower flat zones relative to terrain
  • Vegetation Clearing: Auto-clear trees/rocks in flat zones

World Areas

Defining stations in world-areas.json

Station Manifests

Station configuration and models

Collision System

Tile-based collision and footprints

Biomes

Biome system and vegetation