extends CharacterBody3D ## NS-23: `NavigationAgent3D` path-follow for click-to-move visuals. Server owns `PositionState` / ## `MoveCommand` (NS-16, NS-19); boot snap vs post-verify nav goal from `main.gd`. const MOVE_SPEED: float = 5.0 @onready var _nav_agent: NavigationAgent3D = $NavigationAgent3D func _ready() -> void: _nav_agent.target_position = global_position ## After successful move POST + GET: walk to server target without teleporting. func set_authoritative_nav_goal(world_pos: Vector3) -> void: _nav_agent.target_position = world_pos ## NS-19 rejection or cancel pending path without moving the body. func clear_nav_goal() -> void: velocity = Vector3.ZERO _nav_agent.target_position = global_position ## Boot (and any hard reconcile): teleport to server position and reset agent. func snap_to_server(world_pos: Vector3) -> void: global_position = world_pos velocity = Vector3.ZERO _nav_agent.target_position = world_pos func _physics_process(_delta: float) -> void: if _nav_agent.is_navigation_finished(): velocity = Vector3.ZERO move_and_slide() return var next_path_position: Vector3 = _nav_agent.get_next_path_position() var to_next: Vector3 = next_path_position - global_position to_next.y = 0.0 if to_next.length_squared() < 0.0001: velocity = Vector3.ZERO else: velocity = to_next.normalized() * MOVE_SPEED velocity.y = 0.0 move_and_slide()