48 lines
1.4 KiB
GDScript
48 lines
1.4 KiB
GDScript
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()
|