neon-sprawl/client/scripts/player.gd

69 lines
2.2 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
## If the nav mesh is missing or the agent gives up, steer on XZ toward `target_position`.
const FALLBACK_ARRIVE_EPS: float = 0.4
@onready var _nav_agent: NavigationAgent3D = $NavigationAgent3D
func _ready() -> void:
_nav_agent.set_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.set_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.set_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.set_target_position(world_pos)
func _physics_process(_delta: float) -> void:
var nav_map: RID = _nav_agent.get_navigation_map()
if NavigationServer3D.map_get_iteration_id(nav_map) == 0:
velocity = Vector3.ZERO
move_and_slide()
return
if _nav_agent.is_navigation_finished():
var target: Vector3 = _nav_agent.target_position
var flat_target := Vector3(target.x, global_position.y, target.z)
var to_target: Vector3 = flat_target - global_position
to_target.y = 0.0
if to_target.length_squared() > FALLBACK_ARRIVE_EPS * FALLBACK_ARRIVE_EPS:
velocity = to_target.normalized() * MOVE_SPEED
velocity.y = 0.0
else:
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:
var to_final: Vector3 = _nav_agent.target_position - global_position
to_final.y = 0.0
if to_final.length_squared() > 0.0001:
velocity = to_final.normalized() * MOVE_SPEED
velocity.y = 0.0
else:
velocity = Vector3.ZERO
else:
velocity = to_next.normalized() * MOVE_SPEED
velocity.y = 0.0
move_and_slide()