-- Agrarian terrain tile registry prototype. -- This schema is intentionally separate from player/world persistence so -- terrain packages can be regenerated without overwriting player history. CREATE TABLE IF NOT EXISTS terrain_tiles ( tile_id TEXT PRIMARY KEY, display_name TEXT NOT NULL, grid_scheme TEXT NOT NULL, projection TEXT NOT NULL, utm_zone TEXT, easting_min_m INTEGER NOT NULL, northing_min_m INTEGER NOT NULL, easting_max_m INTEGER NOT NULL, northing_max_m INTEGER NOT NULL, tile_size_m INTEGER NOT NULL CHECK (tile_size_m = 1000), center_latitude REAL NOT NULL CHECK (center_latitude >= -90 AND center_latitude <= 90), center_longitude REAL NOT NULL CHECK (center_longitude >= -180 AND center_longitude <= 180), status TEXT NOT NULL CHECK (status IN ( 'unknown', 'queued', 'source_data_found', 'generated', 'validated', 'packaged', 'published', 'deprecated', 'blocked' )), biome_primary TEXT NOT NULL DEFAULT 'unknown', generation_version INTEGER NOT NULL DEFAULT 0, package_version INTEGER NOT NULL DEFAULT 0, notes TEXT NOT NULL DEFAULT '', created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_terrain_tiles_grid ON terrain_tiles (grid_scheme, projection, utm_zone, easting_min_m, northing_min_m); CREATE INDEX IF NOT EXISTS idx_terrain_tiles_status ON terrain_tiles (status); CREATE TABLE IF NOT EXISTS terrain_tile_neighbors ( tile_id TEXT NOT NULL, direction TEXT NOT NULL CHECK (direction IN ('n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw')), neighbor_tile_id TEXT NOT NULL, PRIMARY KEY (tile_id, direction), FOREIGN KEY (tile_id) REFERENCES terrain_tiles(tile_id), FOREIGN KEY (neighbor_tile_id) REFERENCES terrain_tiles(tile_id) ); CREATE TABLE IF NOT EXISTS terrain_tile_sources ( tile_source_id INTEGER PRIMARY KEY AUTOINCREMENT, tile_id TEXT NOT NULL, source_kind TEXT NOT NULL, source_name TEXT NOT NULL, source_uri TEXT NOT NULL DEFAULT '', license_name TEXT NOT NULL DEFAULT '', source_version TEXT NOT NULL DEFAULT '', coverage_status TEXT NOT NULL CHECK (coverage_status IN ( 'needed', 'candidate', 'confirmed', 'missing', 'not_applicable' )), FOREIGN KEY (tile_id) REFERENCES terrain_tiles(tile_id) ); CREATE INDEX IF NOT EXISTS idx_terrain_tile_sources_tile ON terrain_tile_sources (tile_id, source_kind); CREATE TABLE IF NOT EXISTS terrain_tile_packages ( package_id TEXT PRIMARY KEY, tile_id TEXT NOT NULL, package_version INTEGER NOT NULL, unreal_engine_version TEXT NOT NULL, world_partition_ready INTEGER NOT NULL DEFAULT 0 CHECK (world_partition_ready IN (0, 1)), package_uri TEXT NOT NULL DEFAULT '', content_hash TEXT NOT NULL DEFAULT '', package_size_bytes INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, published_at TEXT, FOREIGN KEY (tile_id) REFERENCES terrain_tiles(tile_id) ); CREATE INDEX IF NOT EXISTS idx_terrain_tile_packages_tile ON terrain_tile_packages (tile_id, package_version); CREATE TABLE IF NOT EXISTS terrain_tile_generation_jobs ( job_id TEXT PRIMARY KEY, tile_id TEXT NOT NULL, job_type TEXT NOT NULL, status TEXT NOT NULL CHECK (status IN ( 'queued', 'running', 'succeeded', 'failed', 'cancelled' )), requested_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, started_at TEXT, finished_at TEXT, log_uri TEXT NOT NULL DEFAULT '', error_summary TEXT NOT NULL DEFAULT '', FOREIGN KEY (tile_id) REFERENCES terrain_tiles(tile_id) ); CREATE INDEX IF NOT EXISTS idx_terrain_tile_generation_jobs_tile ON terrain_tile_generation_jobs (tile_id, status);