feat: synchronize authoritative npc position
- NpcVisual emits position_changed signal during _physics_process - SimulationManager.synchronize_npc_position() writes active position into SimNPC state on movement, arrival, and navigation failure - WorldViewManager forwards position_changed and syncs before despawn/reload - SimNPC stores travel_target_position and has_travel_target as versioned state; NPCStateRecord v2 persists them with v1 migration - WorldViewManager.spawn_npc_visual() resumes travel for traveling NPCs via SimulationManager.request_current_travel() - WorldViewManager.despawn_npc_visual() syncs position before removal - WorldViewManager.reload_npc_visual() spawns a visual from persisted state without rerolling target selection - tests/npc_visual_lifecycle_test.gd proves unload/reload preserves action, target, reservation, position, RNG state, and checksum - simulation_state_serialization_test adds legacy v1 NPC migration test that does not invent an active travel target
This commit is contained in:
@@ -2,6 +2,7 @@ extends CharacterBody3D
|
||||
|
||||
signal arrived_at_target(sim_id: int)
|
||||
signal navigation_failed(sim_id: int)
|
||||
signal position_changed(sim_id: int, active_position: Vector3)
|
||||
|
||||
const DEBUG_LOGS := true
|
||||
|
||||
@@ -123,6 +124,8 @@ func _physics_process(delta: float) -> void:
|
||||
velocity.y = 0.0
|
||||
|
||||
move_and_slide()
|
||||
if not global_position.is_equal_approx(prev_pos):
|
||||
position_changed.emit(sim_id, global_position)
|
||||
|
||||
var minimum_progress := move_speed * delta * 0.1
|
||||
if global_position.distance_squared_to(prev_pos) < minimum_progress * minimum_progress:
|
||||
|
||||
Reference in New Issue
Block a user