NEO-25: route E/R interact via main _unhandled_key_input for reliable input
parent
0e72d98177
commit
06d9104157
|
|
@ -91,7 +91,7 @@ On boot, **`InteractablesCatalogClient`** **`GET`s** **`/game/world/interactable
|
|||
1. Run the game server and client as in NEO-7.
|
||||
2. **F5** in Godot: after catalog load, two interactable sites appear (center + **+X / −Z** floor, anchor **(12, 0.5, −6)** — clear of the gray **Obstacle** near **(6, 1, 5)**). Default spawn **(-5, 0.9, -5)** is out of range of the **center** node (3 m); markers near **origin** stay **dim** until you **WASD** within horizontal **3** m of **(0, 0.5, 0)** on X/Z — then that pair **brightens**.
|
||||
3. Press **E** (**`interact`**): Output **`allowed=true`** when the **terminal** pair glows; **`allowed=false`** / **`out_of_range`** when dim. Walk toward **(12, −6)** until the **second** pair glows; press **R** (**`interact_secondary`**) for **`allowed=true`** on the resource node.
|
||||
4. Interaction uses **`_input`** (and key fallbacks) so keys register in the embedded **Game** dock; click the game view if the editor had focus elsewhere.
|
||||
4. **E** / **R** are handled in **`main.gd`** **`_unhandled_key_input`** and forwarded to **`InteractionRequestClient`** (same pattern as dev keys) so they still register in the embedded **Game** dock; click the game view if the editor had focus elsewhere.
|
||||
|
||||
Full checklist: [`docs/manual-qa/NEO-25.md`](../manual-qa/NEO-25.md).
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ extends Node
|
|||
|
||||
## NS-18 / NEO-25: POST InteractionRequest; prints server allow/deny to Output (prototype).
|
||||
## [kbd]E[/kbd] → [code]prototype_terminal[/code]; [kbd]R[/kbd] → [code]prototype_resource_node_alpha[/code]
|
||||
## (stable contract ids — must match server registry).
|
||||
## (stable contract ids — must match server registry). Key handling is delegated from
|
||||
## [code]main.gd[/code] [method Node._unhandled_key_input] (see [method post_interact_terminal] /
|
||||
## [method post_interact_resource]) so the embedded Game dock still receives E/R reliably.
|
||||
|
||||
const ID_TERMINAL := "prototype_terminal"
|
||||
const ID_RESOURCE_NODE := "prototype_resource_node_alpha"
|
||||
|
|
@ -28,17 +30,12 @@ func _ready() -> void:
|
|||
_http.request_completed.connect(_on_request_completed)
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("interact"):
|
||||
_post_interact(ID_TERMINAL)
|
||||
elif event.is_action_pressed("interact_secondary"):
|
||||
_post_interact(ID_RESOURCE_NODE)
|
||||
elif event is InputEventKey:
|
||||
var k := event as InputEventKey
|
||||
if k.pressed and not k.echo and (k.physical_keycode == KEY_E or k.keycode == KEY_E):
|
||||
_post_interact(ID_TERMINAL)
|
||||
elif k.pressed and not k.echo and (k.physical_keycode == KEY_R or k.keycode == KEY_R):
|
||||
_post_interact(ID_RESOURCE_NODE)
|
||||
func post_interact_terminal() -> void:
|
||||
_post_interact(ID_TERMINAL)
|
||||
|
||||
|
||||
func post_interact_resource() -> void:
|
||||
_post_interact(ID_RESOURCE_NODE)
|
||||
|
||||
|
||||
func _base_root() -> String:
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ var _dev_obstacle_smoke: Node3D
|
|||
@onready var _player_pos_label: Label = $UICanvas/PlayerPositionLabel
|
||||
@onready var _target_lock_label: Label = $UICanvas/TargetLockLabel
|
||||
@onready var _target_client: Node = $TargetSelectionClient
|
||||
@onready var _interaction_client: Node = $InteractionRequestClient
|
||||
@onready var _floor: StaticBody3D = $World/NavigationRegion3D/Floor
|
||||
|
||||
|
||||
|
|
@ -279,11 +280,34 @@ func _on_move_rejected(reason_code: String) -> void:
|
|||
## **F9** / **F10** are debugger shortcuts in the embedded game; use the Input Map action.
|
||||
## For a true **freed-node** occluder test, reload the scene or remove the body in the editor.
|
||||
func _unhandled_key_input(event: InputEvent) -> void:
|
||||
# NEO-25: route interact keys here — `InteractionRequestClient._input` is unreliable in the
|
||||
# embedded Game dock / focus order; `_unhandled_key_input` on the scene root still fires.
|
||||
if event.is_action_pressed("interact"):
|
||||
_forward_interact_post("post_interact_terminal")
|
||||
return
|
||||
if event.is_action_pressed("interact_secondary"):
|
||||
_forward_interact_post("post_interact_resource")
|
||||
return
|
||||
if event is InputEventKey:
|
||||
var k := event as InputEventKey
|
||||
if k.pressed and not k.echo and (k.physical_keycode == KEY_E or k.keycode == KEY_E):
|
||||
_forward_interact_post("post_interact_terminal")
|
||||
return
|
||||
if k.pressed and not k.echo and (k.physical_keycode == KEY_R or k.keycode == KEY_R):
|
||||
_forward_interact_post("post_interact_resource")
|
||||
return
|
||||
if not event.is_action_pressed("dev_toggle_occluder_obstacle"):
|
||||
return
|
||||
call_deferred("_dev_toggle_obstacle_smoke_deferred")
|
||||
|
||||
|
||||
func _forward_interact_post(method: String) -> void:
|
||||
if not is_instance_valid(_interaction_client):
|
||||
return
|
||||
if _interaction_client.has_method(method):
|
||||
_interaction_client.call(method)
|
||||
|
||||
|
||||
func _dev_toggle_obstacle_smoke_deferred() -> void:
|
||||
var obstacle := _dev_obstacle_smoke
|
||||
if obstacle == null or not is_instance_valid(obstacle):
|
||||
|
|
|
|||
Loading…
Reference in New Issue