refactor(server): address PR #16 review feedback

Hoshe + Tyre review items:
- Use StableId consistently for wire entity_id (H4) across observer,
  observation, interpretation, and interaction systems
- Make NearbyInteractionBuffer.interactions private with take() (H1/H20)
- Add system ordering constraint for compute_nearby_interactions (H5)
- Panic on missing PlayerCharacter in input processing (H2)
- Remove redundant paused field from GameTime (Tyre8)
- Remove #[serde(default)] from nearby_interactions (H3)
- Change NearbyInteraction.distance from f32 to u32 (H8)
- Add sort stability for equal verb priorities (H6)
- Scope constants to pub(crate) (H7)
- Add debug_assert for last_observed_tick ordering (H10)
- Strengthen unregistered entity handling to debug_assert + error (H11)
- Document fractional tick accumulation (Tyre9)
- Extract collect_remembered_entities helper (Tyre2/H17)
- Add half_rate_no_drift_over_10000_frames test (H14)
- Add mid-range and deterministic sort tests (H15)
- Add fixture version assertion (H16)
- Regenerate msgpack fixtures for wire format changes

146 unit + 19 integration tests pass, zero clippy warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 20:14:35 +01:00
co-authored by Claude Opus 4.6
parent 458be0f621
commit 9943684f2c
19 changed files with 232 additions and 136 deletions
-1
View File
@@ -39,7 +39,6 @@ fn snapshot_roundtrip_over_unix_socket() {
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
paused: false,
tick_rate: TickRate::Full,
},
player_facing: FacingDirection::North,
-1
View File
@@ -25,7 +25,6 @@ fn snapshot_roundtrip_over_tcp() {
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
paused: false,
tick_rate: TickRate::Full,
},
player_facing: FacingDirection::North,
+1 -1
View File
@@ -68,7 +68,7 @@ fn player_moves_north_through_full_pipeline() {
// v2 fields populated
assert_eq!(snapshot.game_time.day, 0);
assert_eq!(snapshot.game_time.day_phase, settled_reach_server::simulation::time::DayPhase::Morning);
assert!(!snapshot.game_time.paused);
assert_eq!(snapshot.game_time.tick_rate, settled_reach_server::simulation::time::TickRate::Full);
let player_entity = &snapshot.entities[0];
// Player started at (16, 16, 0), moved north (y-1) to (16, 15, 0)
-2
View File
@@ -24,7 +24,6 @@ fn fixture_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
paused: false,
tick_rate: TickRate::Full,
},
player_facing: FacingDirection::North,
@@ -158,7 +157,6 @@ fn generate_msgpack_fixtures() {
day: 1,
time_of_day: 720,
day_phase: DayPhase::Evening,
paused: false,
tick_rate: TickRate::Full,
},
player_facing: FacingDirection::Southeast,
+3 -5
View File
@@ -13,7 +13,6 @@ fn test_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot {
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
paused: false,
tick_rate: TickRate::Full,
},
player_facing: FacingDirection::North,
@@ -127,8 +126,9 @@ fn all_fixtures_deserialize() {
let bytes = fs::read(&path).unwrap_or_else(|_| panic!("read fixture {}", name));
if name.starts_with("snapshot") {
rmp_serde::from_slice::<ObserverSnapshot>(&bytes)
let snap = rmp_serde::from_slice::<ObserverSnapshot>(&bytes)
.unwrap_or_else(|e| panic!("deserialize snapshot fixture {}: {}", name, e));
assert_eq!(snap.version, 4, "fixture {} has wrong version", name);
} else if name.starts_with("input_batch") {
rmp_serde::from_slice::<Vec<PlayerInput>>(&bytes)
.unwrap_or_else(|e| panic!("deserialize batch input fixture {}: {}", name, e));
@@ -186,7 +186,6 @@ fn snapshot_v2_fields_roundtrip() {
day: 3,
time_of_day: 720,
day_phase: DayPhase::Evening,
paused: true,
tick_rate: TickRate::Paused,
},
player_facing: FacingDirection::Southeast,
@@ -224,7 +223,7 @@ fn snapshot_v2_fields_roundtrip() {
assert_eq!(decoded.game_time.day, 3);
assert_eq!(decoded.game_time.time_of_day, 720);
assert_eq!(decoded.game_time.day_phase, DayPhase::Evening);
assert!(decoded.game_time.paused);
assert_eq!(decoded.game_time.tick_rate, TickRate::Paused);
assert_eq!(decoded.player_facing, FacingDirection::Southeast);
assert_eq!(decoded.visible_tiles.len(), 2);
assert_eq!(decoded.visible_tiles[0].visibility, VisibilitySector::Forward);
@@ -254,7 +253,6 @@ fn all_facing_direction_variants_roundtrip() {
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
paused: false,
tick_rate: TickRate::Full,
},
player_facing: dir,