feat(simulation): atlas proxy layers + data-delivery endpoints (T-960, T-949)
T-960: RoadGraphLayer (L2 edges/junctions, MaintenanceAuthority, rail flag, named routes) + SettlementLayer (name/position/size-class/is_capital/is_port from T-955 placements) as new Option fields on AtlasLayerResponse — T-1046 precedent; layer_proxy doc comment corrected (cascade runs through RoadGraph, client up_to ignored). T-949: new StarMapRequest/StarMapResponse (raw JSON passthrough of the star_map_data.json bake) + CityNamesRequest/CityNamesResponse (atlas_city_names via CityContextReader) with defense-in-depth Sol exclusion (GJ-0 system id OR settlement_wave='origin', D-236). Inbound demux extended with mandatory boolean discriminator fields (serde ignores unknown fields — optional-shape sniffing would be ambiguous); AtlasLayerRequest unchanged. SimBridge trait +2 methods, implemented on TcpBridge + LocalBridge. CityPlacement/CityRecord gained name/population/is_capital (BodyWorldState cache-hit path stays DB-free). ~30 new unit tests incl. demux disambiguation + Sol branches; gen_fixtures extended for road/settlement samples. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -338,7 +338,8 @@ fn single_tick_drains_all_ready_inbound_frames() {
|
||||
use settled_reach_server::atlas::cascade::CascadeLayer;
|
||||
use settled_reach_server::atlas::layer_proxy::AtlasLayerRequest;
|
||||
use settled_reach_server::bridge::{
|
||||
receive_bridge_inputs, AtlasRequestBuffer, BridgeResource, HandshakeState, ServerRunning,
|
||||
receive_bridge_inputs, AtlasRequestBuffer, BridgeResource, CityNamesRequestBuffer,
|
||||
HandshakeState, ServerRunning, StarMapRequestBuffer,
|
||||
};
|
||||
use settled_reach_server::simulation::input::InputQueue;
|
||||
|
||||
@@ -379,6 +380,8 @@ fn single_tick_drains_all_ready_inbound_frames() {
|
||||
world.insert_resource(HandshakeState::Complete);
|
||||
world.init_resource::<SimErrorBuffer>();
|
||||
world.init_resource::<AtlasRequestBuffer>();
|
||||
world.init_resource::<StarMapRequestBuffer>();
|
||||
world.init_resource::<CityNamesRequestBuffer>();
|
||||
|
||||
world
|
||||
.run_system_once(receive_bridge_inputs)
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
|
||||
use settled_reach_server::atlas::body_world_state::{DrainageBasin, RiverNetwork};
|
||||
use settled_reach_server::atlas::layer1::Layer1Output;
|
||||
use settled_reach_server::atlas::layer_proxy::{AtlasLayerResponse, AtlasLayerStatus};
|
||||
use settled_reach_server::atlas::layer_proxy::{
|
||||
AtlasLayerResponse, AtlasLayerStatus, RoadGraphEdge, RoadGraphLayer, RoadGraphNode,
|
||||
SettlementEntry, SettlementLayer, SettlementSizeClass,
|
||||
};
|
||||
use settled_reach_server::atlas::road_graph::RoadNodeKind;
|
||||
use settled_reach_server::bridge::types::*;
|
||||
use settled_reach_server::simulation::generator::{
|
||||
AttractorType, GeographicAttractor, SubBiomeVariant,
|
||||
AttractorType, GeographicAttractor, MaintenanceAuthority, SubBiomeVariant,
|
||||
};
|
||||
use settled_reach_server::simulation::poi::PoiCategory;
|
||||
use settled_reach_server::simulation::time::{DayPhase, TickRate};
|
||||
@@ -568,11 +572,58 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
grid_h: 256,
|
||||
district_basin_dirs: std::collections::BTreeMap::new(),
|
||||
};
|
||||
// T-960 §1/§2: a small populated RoadGraphLayer + SettlementLayer, one
|
||||
// settlement (a capital) connected to one waypoint-free short edge.
|
||||
let road_graph = RoadGraphLayer {
|
||||
nodes: vec![
|
||||
RoadGraphNode {
|
||||
position: (12, 58),
|
||||
kind: RoadNodeKind::Settlement,
|
||||
city_id: Some(1),
|
||||
},
|
||||
RoadGraphNode {
|
||||
position: (20, 70),
|
||||
kind: RoadNodeKind::Settlement,
|
||||
city_id: Some(2),
|
||||
},
|
||||
],
|
||||
edges: vec![RoadGraphEdge {
|
||||
from: 0,
|
||||
to: 1,
|
||||
path: vec![(12, 58), (16, 64), (20, 70)],
|
||||
maintenance: MaintenanceAuthority::Administrative,
|
||||
is_rail: false,
|
||||
named_route_id: None,
|
||||
}],
|
||||
};
|
||||
let settlements = SettlementLayer {
|
||||
settlements: vec![
|
||||
SettlementEntry {
|
||||
city_id: 1,
|
||||
name: "Port Aldren".into(),
|
||||
position: (12, 58),
|
||||
size_class: SettlementSizeClass::Major,
|
||||
is_capital: true,
|
||||
is_port: true,
|
||||
},
|
||||
SettlementEntry {
|
||||
city_id: 2,
|
||||
name: "Farmstead Rell".into(),
|
||||
position: (20, 70),
|
||||
size_class: SettlementSizeClass::Minor,
|
||||
is_capital: false,
|
||||
is_port: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let ready = AtlasLayerResponse {
|
||||
body_id: "GJ1c".into(),
|
||||
status: AtlasLayerStatus::Ready,
|
||||
layer1: Some(layer1),
|
||||
district_grid: None,
|
||||
road_graph: Some(road_graph),
|
||||
settlements: Some(settlements),
|
||||
};
|
||||
write_fixture(
|
||||
"atlas_response_ready",
|
||||
@@ -584,6 +635,8 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
status: AtlasLayerStatus::Pending,
|
||||
layer1: None,
|
||||
district_grid: None,
|
||||
road_graph: None,
|
||||
settlements: None,
|
||||
};
|
||||
write_fixture(
|
||||
"atlas_response_pending",
|
||||
@@ -595,6 +648,8 @@ fn generate_atlas_layer_response_fixtures() {
|
||||
status: AtlasLayerStatus::NotFound,
|
||||
layer1: None,
|
||||
district_grid: None,
|
||||
road_graph: None,
|
||||
settlements: None,
|
||||
};
|
||||
write_fixture(
|
||||
"atlas_response_not_found",
|
||||
|
||||
Reference in New Issue
Block a user