Files
settled-reach/server/tests/gen_fixtures.rs
T
jpmschweitzerandClaude Opus 4.6 22de6c714f fix(simulation): address PR #12 review — z-level filter, visible tile dedup, version bump
- Filter remembered entities by z-level (Hoshe + Tyre warning)
- Skip remembered ghosts on currently visible tiles (Hoshe warning)
- Bump ObserverSnapshot version to 3 (Tyre suggestion)
- Add edge case tests: visible tile collision, different z-level,
  knowledge without position (Hoshe suggestion)
- Regenerate msgpack fixtures for v3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:47:35 +01:00

225 lines
6.8 KiB
Rust

//! Generate MessagePack fixture files for cross-language testing (D-030 Layer 1).
//! Run with: cargo test --test gen_fixtures -- --ignored
use settled_reach_server::bridge::types::*;
use settled_reach_server::simulation::time::DayPhase;
use std::fs;
use std::path::Path;
fn write_fixture(name: &str, bytes: &[u8]) {
// Write directly into the Godot project's test fixtures (single source of truth)
let dir = Path::new("../client/tests/fixtures/msgpack");
fs::create_dir_all(dir).expect("create fixture dir");
let path = dir.join(format!("{}.msgpack", name));
fs::write(&path, bytes).expect("write fixture");
eprintln!("Wrote {} ({} bytes)", path.display(), bytes.len());
}
/// Helper to create a minimal v2 snapshot for fixtures
fn fixture_snapshot(tick: u64, entities: Vec<VisibleEntity>) -> ObserverSnapshot {
ObserverSnapshot {
version: 3,
tick,
game_time: GameTime {
day: 0,
time_of_day: 0,
day_phase: DayPhase::Morning,
paused: false,
},
player_facing: FacingDirection::North,
entities,
visible_tiles: vec![],
}
}
#[test]
#[ignore] // Run manually: cargo test --test gen_fixtures -- --ignored
fn generate_msgpack_fixtures() {
// Snapshot with one NPC entity
let snapshot = fixture_snapshot(
42,
vec![VisibleEntity {
entity_id: 1,
x: 10.0,
y: 20.0,
z: 0,
kind: EntityKind::Npc,
visibility: VisibilitySector::Forward,
relationship: RelationshipState::Unknown,
observation: EntityVisibility::Visible,
}],
);
write_fixture(
"snapshot_one_npc",
&rmp_serde::to_vec_named(&snapshot).unwrap(),
);
// Empty snapshot
let empty = fixture_snapshot(0, vec![]);
write_fixture("snapshot_empty", &rmp_serde::to_vec_named(&empty).unwrap());
// PlayerInput: MoveNorth
let input_north = PlayerInput {
tick: 100,
action: PlayerAction::MoveNorth,
};
write_fixture(
"input_move_north",
&rmp_serde::to_vec_named(&input_north).unwrap(),
);
// PlayerInput: UsePerceptionMode
let input_perception = PlayerInput {
tick: 200,
action: PlayerAction::UsePerceptionMode("thermal".to_string()),
};
write_fixture(
"input_perception_mode",
&rmp_serde::to_vec_named(&input_perception).unwrap(),
);
// Snapshot with Player entity
let snapshot_player = fixture_snapshot(
1,
vec![VisibleEntity {
entity_id: 100,
x: 16.5,
y: 16.5,
z: 0,
kind: EntityKind::Player,
visibility: VisibilitySector::Forward,
relationship: RelationshipState::Unknown,
observation: EntityVisibility::Visible,
}],
);
write_fixture(
"snapshot_player",
&rmp_serde::to_vec_named(&snapshot_player).unwrap(),
);
// Snapshot with multiple entities and all EntityKind variants
let snapshot_multi = fixture_snapshot(
999,
vec![
VisibleEntity {
entity_id: 1,
x: 16.5,
y: 16.5,
z: 0,
kind: EntityKind::Player,
visibility: VisibilitySector::Forward,
relationship: RelationshipState::Known,
observation: EntityVisibility::Visible,
},
VisibleEntity {
entity_id: 2,
x: 5.0,
y: 10.0,
z: 0,
kind: EntityKind::Npc,
visibility: VisibilitySector::Peripheral,
relationship: RelationshipState::Unknown,
observation: EntityVisibility::Visible,
},
VisibleEntity {
entity_id: 3,
x: 15.5,
y: 3.0,
z: 1,
kind: EntityKind::Object,
visibility: VisibilitySector::Forward,
relationship: RelationshipState::Unknown,
observation: EntityVisibility::Visible,
},
VisibleEntity {
entity_id: 4,
x: 0.0,
y: 0.0,
z: -1,
kind: EntityKind::Terrain,
visibility: VisibilitySector::Forward,
relationship: RelationshipState::Unknown,
observation: EntityVisibility::Visible,
},
],
);
write_fixture(
"snapshot_multi_entity",
&rmp_serde::to_vec_named(&snapshot_multi).unwrap(),
);
// v2 snapshot with visible_tiles and game_time populated
let snapshot_v2_full = ObserverSnapshot {
version: 3,
tick: 500,
game_time: GameTime {
day: 1,
time_of_day: 720,
day_phase: DayPhase::Evening,
paused: false,
},
player_facing: FacingDirection::Southeast,
entities: vec![VisibleEntity {
entity_id: 1,
x: 10.5,
y: 10.5,
z: 0,
kind: EntityKind::Player,
visibility: VisibilitySector::Forward,
relationship: RelationshipState::Unknown,
observation: EntityVisibility::Visible,
}],
visible_tiles: vec![
VisibleTile {
x: 10,
y: 10,
z: 0,
visibility: VisibilitySector::Forward,
},
VisibleTile {
x: 11,
y: 10,
z: 0,
visibility: VisibilitySector::Peripheral,
},
VisibleTile {
x: 10,
y: 9,
z: 0,
visibility: VisibilitySector::Forward,
},
],
};
write_fixture(
"snapshot_v2_full",
&rmp_serde::to_vec_named(&snapshot_v2_full).unwrap(),
);
// Batch input: Vec<PlayerInput> with two actions (D-030 Layer 1 bidirectional symmetry)
let input_batch = vec![
PlayerInput {
tick: 0,
action: PlayerAction::MoveNorth,
},
PlayerInput {
tick: 0,
action: PlayerAction::Interact,
},
];
write_fixture(
"input_batch_two",
&rmp_serde::to_vec_named(&input_batch).unwrap(),
);
// Diagonal movement fixtures (clockwise: NE, SE, SW, NW)
for (name, action) in [
("input_move_northeast", PlayerAction::MoveNortheast),
("input_move_southeast", PlayerAction::MoveSoutheast),
("input_move_southwest", PlayerAction::MoveSouthwest),
("input_move_northwest", PlayerAction::MoveNorthwest),
] {
let input = PlayerInput { tick: 100, action };
write_fixture(name, &rmp_serde::to_vec_named(&input).unwrap());
}
}