Files
settled-reach/server/tests/movement.rs
T
jpmschweitzerandClaude Opus 4.6 f87bd2b0e5 feat(simulation): add entity-entity collision
validate_movement now checks both terrain walkability AND tile
occupancy. Builds a spatial index of occupied tiles from stationary
entities, then resolves movers in order — first valid claim wins.

Same spatial pattern needed for D-026 simulation tiers (30-80 active
NPCs) and future pathfinding occupied-tile awareness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 20:15:24 +01:00

83 lines
2.1 KiB
Rust

use bevy_app::prelude::*;
use settled_reach_server::simulation::movement::*;
use settled_reach_server::simulation::time::SimulationTime;
use settled_reach_server::simulation::SimulationPlugin;
#[test]
fn movement_validated_within_app() {
let mut app = App::new();
app.add_plugins(SimulationPlugin);
// Insert a walkability map with one blocked tile
let mut map = WalkabilityMap::new(10, 10, 1);
map.set_walkable(&TilePosition::new(3, 3, 0), false);
app.insert_resource(map);
// Spawn mover (walkable target) and blocked entity
let mover = app
.world_mut()
.spawn((
TilePosition::new(5, 5, 0),
MoveIntent {
target: TilePosition::new(5, 4, 0),
},
))
.id();
let blocked = app
.world_mut()
.spawn((
TilePosition::new(3, 4, 0),
MoveIntent {
target: TilePosition::new(3, 3, 0),
},
))
.id();
app.update();
// Mover moved
assert_eq!(
*app.world().get::<TilePosition>(mover).unwrap(),
TilePosition::new(5, 4, 0)
);
// Blocked stayed
assert_eq!(
*app.world().get::<TilePosition>(blocked).unwrap(),
TilePosition::new(3, 4, 0)
);
// Tick advanced
assert_eq!(app.world().resource::<SimulationTime>().tick, 1);
// Both intents consumed
assert!(app.world().get::<MoveIntent>(mover).is_none());
assert!(app.world().get::<MoveIntent>(blocked).is_none());
}
#[test]
fn entity_collision_blocks_movement() {
let mut app = App::new();
app.add_plugins(SimulationPlugin);
app.insert_resource(WalkabilityMap::new(10, 10, 1));
// Stationary entity at (5,4)
app.world_mut().spawn(TilePosition::new(5, 4, 0));
// Mover tries to move into occupied tile
let mover = app
.world_mut()
.spawn((
TilePosition::new(5, 5, 0),
MoveIntent {
target: TilePosition::new(5, 4, 0),
},
))
.id();
app.update();
assert_eq!(
*app.world().get::<TilePosition>(mover).unwrap(),
TilePosition::new(5, 5, 0)
);
}