refactor(simulation): drop PROTOCOL_VERSION from bridge handshake (#874, D-192)
Removes the PROTOCOL_VERSION lockstep handshake across the bridge transports. HandshakeMessage is now an empty marker indicating the server is ready; the client sends StartupMessage next. Field-presence and roundtrip behavioral tests are retained — tautological version-literal assertions were deleted in Sprint 36. After this lands, genuine schema drift surfaces as MessagePack missing-field errors downstream, which is the intended signal per D-192. Client ticket #875 is blocked by this commit and will ride the same wave; server schema changes in #878 (character_archetype removal) also depend on PROTOCOL_VERSION already being gone. types.rs changes are bundled with the broader #877/#878 dead-code sweep in the following commit, since they share the same file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -96,17 +96,17 @@ impl SimBridge for LocalBridge {
|
||||
}
|
||||
|
||||
fn send_handshake(&self) -> Result<(), BridgeError> {
|
||||
use super::types::{HandshakeMessage, PROTOCOL_VERSION};
|
||||
let msg = HandshakeMessage {
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
};
|
||||
// D-192: HandshakeMessage carries no version. Send an empty marker so the
|
||||
// client knows to begin the startup sequence (send StartupMessage next).
|
||||
use super::types::HandshakeMessage;
|
||||
let msg = HandshakeMessage {};
|
||||
let payload = rmp_serde::to_vec_named(&msg)?;
|
||||
let mut writer = self
|
||||
.writer
|
||||
.lock()
|
||||
.map_err(|e| BridgeError::MutexPoisoned(format!("writer: {}", e)))?;
|
||||
write_framed(writer.get_mut(), &payload)?;
|
||||
tracing::info!("sent handshake: protocol_version={}", PROTOCOL_VERSION);
|
||||
tracing::info!("sent handshake");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -158,10 +158,10 @@ impl SimBridge for TcpBridge {
|
||||
}
|
||||
|
||||
fn send_handshake(&self) -> Result<(), BridgeError> {
|
||||
use super::types::{HandshakeMessage, PROTOCOL_VERSION};
|
||||
let msg = HandshakeMessage {
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
};
|
||||
// D-192: HandshakeMessage carries no version. Send an empty marker so the
|
||||
// client knows to begin the startup sequence (send StartupMessage next).
|
||||
use super::types::HandshakeMessage;
|
||||
let msg = HandshakeMessage {};
|
||||
let payload = rmp_serde::to_vec_named(&msg)?;
|
||||
let mut writer = self
|
||||
.writer
|
||||
@@ -173,7 +173,7 @@ impl SimBridge for TcpBridge {
|
||||
let result = write_framed(stream, &payload);
|
||||
stream.set_nonblocking(true).map_err(BridgeError::Io)?;
|
||||
result?;
|
||||
tracing::info!("sent handshake: protocol_version={}", PROTOCOL_VERSION);
|
||||
tracing::info!("sent handshake");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -220,7 +220,6 @@ mod tests {
|
||||
|
||||
fn make_snapshot() -> ObserverSnapshot {
|
||||
ObserverSnapshot {
|
||||
version: PROTOCOL_VERSION,
|
||||
tick: 42,
|
||||
game_time: GameTime {
|
||||
day: 0,
|
||||
@@ -427,7 +426,6 @@ mod tests {
|
||||
#[test]
|
||||
fn empty_snapshot_no_panic() {
|
||||
let snap = ObserverSnapshot {
|
||||
version: PROTOCOL_VERSION,
|
||||
tick: 0,
|
||||
game_time: GameTime {
|
||||
day: 0,
|
||||
|
||||
+9
-28
@@ -153,7 +153,7 @@ fn main() {
|
||||
app.add_plugins(settled_reach_server::npc::NpcPlugin);
|
||||
app.add_plugins(settled_reach_server::storyteller::StorytellerPlugin);
|
||||
app.add_plugins(settled_reach_server::settings::SettingsPlugin);
|
||||
app.add_plugins(settled_reach_server::bookmark::BookmarkPlugin);
|
||||
app.add_plugins(settled_reach_server::bookmark::BookmarkPlugin::default());
|
||||
|
||||
// Initialize culture resolver (#679, D-128).
|
||||
// systems.db is shipped read-only alongside the binary.
|
||||
@@ -216,20 +216,17 @@ fn main() {
|
||||
),
|
||||
);
|
||||
|
||||
// Character archetype from client's StartupMessage (#587).
|
||||
let archetype = startup.character_archetype;
|
||||
|
||||
// Gauntlet test world for --test-mode, proof room for normal mode.
|
||||
if test_mode {
|
||||
#[cfg(feature = "gauntlet")]
|
||||
settled_reach_server::test_world::setup_gauntlet(&mut app, archetype);
|
||||
settled_reach_server::test_world::setup_gauntlet(&mut app);
|
||||
#[cfg(not(feature = "gauntlet"))]
|
||||
{
|
||||
eprintln!("--test-mode requires the 'gauntlet' feature");
|
||||
std::process::exit(1);
|
||||
}
|
||||
} else {
|
||||
setup_proof_room(&mut app, archetype, seed);
|
||||
setup_proof_room(&mut app, seed);
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
@@ -325,7 +322,6 @@ fn send_panic_error(app: &App, panic_msg: &str) {
|
||||
|
||||
// Build a minimal snapshot carrying the panic error
|
||||
let snapshot = ObserverSnapshot {
|
||||
version: PROTOCOL_VERSION,
|
||||
tick,
|
||||
game_time: GameTime {
|
||||
day: 0,
|
||||
@@ -394,7 +390,7 @@ fn dump_schedule_graph() {
|
||||
app.add_plugins(settled_reach_server::npc::NpcPlugin);
|
||||
app.add_plugins(settled_reach_server::storyteller::StorytellerPlugin);
|
||||
app.add_plugins(settled_reach_server::settings::SettingsPlugin);
|
||||
app.add_plugins(settled_reach_server::bookmark::BookmarkPlugin);
|
||||
app.add_plugins(settled_reach_server::bookmark::BookmarkPlugin::default());
|
||||
app.insert_resource(settled_reach_server::simulation::rng::SimRng::new(0));
|
||||
|
||||
// Access Schedules resource directly — schedules are populated by plugins
|
||||
@@ -422,11 +418,7 @@ fn dump_schedule_graph() {
|
||||
|
||||
/// Proof room: 32x32 map, wall at (16,14), player at (16,16), 3 NPCs.
|
||||
/// Extracted from the original inline setup for reuse by both test-mode and normal mode.
|
||||
fn setup_proof_room(
|
||||
app: &mut App,
|
||||
archetype: settled_reach_server::bridge::types::CharacterArchetype,
|
||||
world_seed: u64,
|
||||
) {
|
||||
fn setup_proof_room(app: &mut App, world_seed: u64) {
|
||||
use settled_reach_server::knowledge::registry::EntityRegistry;
|
||||
use settled_reach_server::knowledge::KnowledgeGraph;
|
||||
use settled_reach_server::npc::relationships::{RelationshipEdge, RelationshipGraph};
|
||||
@@ -459,19 +451,9 @@ fn setup_proof_room(
|
||||
|
||||
let mut registry = EntityRegistry::new(0);
|
||||
|
||||
// Player at (16,16) — archetype from StartupMessage (#587, D-053)
|
||||
let profile = match archetype {
|
||||
settled_reach_server::bridge::types::CharacterArchetype::Smuggler => {
|
||||
MovementProfile::smuggler()
|
||||
}
|
||||
settled_reach_server::bridge::types::CharacterArchetype::Detective => {
|
||||
MovementProfile::detective()
|
||||
}
|
||||
};
|
||||
let monologue_state = MonologueState {
|
||||
character: archetype.as_monologue_key().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
// Player at (16,16). Archetype-specific spawn logic was removed in Sprint 37
|
||||
// (D-032 purge); per-culture/per-role voice is reintroduced in Phase 6.
|
||||
let profile = MovementProfile::default();
|
||||
let player = app
|
||||
.world_mut()
|
||||
.spawn((
|
||||
@@ -480,12 +462,11 @@ fn setup_proof_room(
|
||||
Facing::default(),
|
||||
KnowledgeGraph::new(),
|
||||
NearbyInteractionBuffer::default(),
|
||||
monologue_state,
|
||||
MonologueState::default(),
|
||||
MonologueBuffer::default(),
|
||||
SprintAnomalyQueue::default(),
|
||||
CognitiveDelay::default(),
|
||||
ListeningFocus::new(TilePosition::new(16, 16, 0)),
|
||||
archetype,
|
||||
profile,
|
||||
profile.initial_stance(),
|
||||
PlayerMoveCooldown::default(),
|
||||
|
||||
@@ -33,7 +33,6 @@ fn snapshot_roundtrip_over_unix_socket() {
|
||||
let bridge = LocalBridge::accept(&server_path).expect("failed to accept");
|
||||
|
||||
let snapshot = ObserverSnapshot {
|
||||
version: PROTOCOL_VERSION,
|
||||
tick: 42,
|
||||
game_time: GameTime {
|
||||
day: 0,
|
||||
|
||||
@@ -19,7 +19,6 @@ fn snapshot_roundtrip_over_tcp() {
|
||||
let bridge = TcpBridge::accept_on(listener).expect("failed to accept");
|
||||
|
||||
let snapshot = ObserverSnapshot {
|
||||
version: PROTOCOL_VERSION,
|
||||
tick: 42,
|
||||
game_time: GameTime {
|
||||
day: 0,
|
||||
|
||||
@@ -99,13 +99,9 @@ fn ipc_round_trip_latency() {
|
||||
let handshake_bytes = read_framed(&mut reader)
|
||||
.expect("read handshake")
|
||||
.expect("server closed before sending HandshakeMessage");
|
||||
let handshake: HandshakeMessage =
|
||||
// D-192: HandshakeMessage carries no version field. Verify it deserialises cleanly.
|
||||
let _handshake: HandshakeMessage =
|
||||
rmp_serde::from_slice(&handshake_bytes).expect("deserialize HandshakeMessage");
|
||||
assert_eq!(
|
||||
handshake.protocol_version, PROTOCOL_VERSION,
|
||||
"handshake version mismatch: server={}, client={}",
|
||||
handshake.protocol_version, PROTOCOL_VERSION
|
||||
);
|
||||
|
||||
let make_input = |tick: u64| PlayerInput {
|
||||
tick,
|
||||
|
||||
Reference in New Issue
Block a user