fix(simulation): address PR #56 review — pipeline extraction, ActiveDialogue, range check
Tyre #1: Extract run_dialogue_pipeline() shared helper — eliminates ~60 lines of duplication between process_talk_interaction and process_dialogue_response (L1-L4 pipeline). Hoshe #1: process_dialogue_response now updates ActiveDialogue with current tick on follow-up selection — prevents stale started_tick. Tyre #4: process_dialogue_response now updates InteractionMemory on follow-up — multi-turn conversations are visible in history. Hoshe #6 / Tyre #6: handle_dialogue_response adds server-side range check (CLOSE_RANGE), matching Talk/Confront pattern (D-010 info boundary). Hoshe #2: Weighted selection fallback replaced with unreachable!() — score_line always returns >= 1, so the fallback was dead code. Hoshe #3: assert!(false, ...) → panic!() in serialization.rs (clippy). Hoshe #4: SetFacing and TeleportToHub added to roundtrip test. Hoshe #5: setup_dialogue_response_world inlined (trivial pass-through). Tyre #2: Doc comment on DialogueCooldownTracker explains per-player-global design choice (line IDs are NPC-scoped per D-035, no collision risk). Tyre #3: CONFRONTATION_LINES comment updated with TODO for D-028/D-035 migration. Tyre #5: DialogueResponse fixture added for cross-language GDScript testing (input_dialogue_response.msgpack). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -288,6 +288,7 @@ pub fn process_player_input(
|
||||
&mut commands,
|
||||
®istry,
|
||||
&player_query,
|
||||
&all_positions,
|
||||
target_entity_id,
|
||||
response_id,
|
||||
);
|
||||
@@ -472,6 +473,10 @@ fn handle_talk(
|
||||
|
||||
/// Handle DialogueResponse action: set DialogueResponseRequest marker (#539).
|
||||
/// The follow-up dialogue pipeline runs in process_dialogue_response (dialogue.rs).
|
||||
///
|
||||
/// Range check: same CLOSE_RANGE as Talk/Confront (D-010 info boundary). The player
|
||||
/// must still be near the NPC to continue a conversation — walking away mid-dialogue
|
||||
/// should not allow remote follow-ups.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn handle_dialogue_response(
|
||||
commands: &mut Commands,
|
||||
@@ -485,10 +490,11 @@ fn handle_dialogue_response(
|
||||
),
|
||||
With<PlayerCharacter>,
|
||||
>,
|
||||
all_positions: &Query<&TilePosition>,
|
||||
target_entity_id: u64,
|
||||
response_id: &str,
|
||||
) {
|
||||
let Ok((player_entity, _, _, _)) = player_query.single() else {
|
||||
let Ok((player_entity, player_pos, _, _)) = player_query.single() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -498,6 +504,22 @@ fn handle_dialogue_response(
|
||||
return;
|
||||
};
|
||||
|
||||
// Server-side range check: reject DialogueResponse if target moved out of range
|
||||
if let Ok(target_pos) = all_positions.get(target_entity) {
|
||||
let distance = player_pos
|
||||
.manhattan_distance(target_pos)
|
||||
.unwrap_or(u32::MAX);
|
||||
if distance > crate::simulation::interaction::CLOSE_RANGE {
|
||||
tracing::info!(
|
||||
target_entity_id,
|
||||
distance,
|
||||
"DialogueResponse: target out of range (max {})",
|
||||
crate::simulation::interaction::CLOSE_RANGE,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
commands
|
||||
.entity(player_entity)
|
||||
.insert(crate::simulation::dialogue::DialogueResponseRequest {
|
||||
|
||||
Reference in New Issue
Block a user