NEO-153: fix gdlint pre-push for contract HUD wiring.
Extract contract HUD main wiring, dedupe deny copy, trim main.gd, and add wiring tests.pull/195/head
parent
6a48315ba5
commit
b9ffd7553b
|
|
@ -10,6 +10,13 @@ const PROTOTYPE_CONTRACT_SEED_BUCKET := "prototype_contract_dev_seed"
|
|||
const ISSUE_IDLE_HINT := "Contract issue: — (Shift+C prototype)"
|
||||
const ISSUE_SENDING_HINT := "Contract issue: sending…"
|
||||
const REWARD_HEADER := "Contract rewards:"
|
||||
const ISSUE_DENY_COPY := {
|
||||
"active_contract_exists": "Contract issue: denied — active contract already issued",
|
||||
"no_eligible_template": "Contract issue: denied — no eligible template (standing/band)",
|
||||
"economy_cap_exceeded": "Contract issue: denied — economy cap exceeded",
|
||||
"invalid_reward_bundle": "Contract issue: denied — invalid reward bundle",
|
||||
"unknown_template": "Contract issue: denied — unknown template",
|
||||
}
|
||||
|
||||
var _contract_client: Node = null
|
||||
var _item_defs_client: Node = null
|
||||
|
|
@ -84,13 +91,14 @@ func try_issue_key_input(event: InputEvent) -> bool:
|
|||
if not event is InputEventKey:
|
||||
return false
|
||||
var k := event as InputEventKey
|
||||
if not k.pressed or k.echo or not k.shift_pressed:
|
||||
return false
|
||||
if k.physical_keycode != KEY_C and k.keycode != KEY_C:
|
||||
return false
|
||||
if not is_instance_valid(_contract_client):
|
||||
return false
|
||||
if not _contract_client.has_method("request_issue"):
|
||||
if (
|
||||
not k.pressed
|
||||
or k.echo
|
||||
or not k.shift_pressed
|
||||
or (k.physical_keycode != KEY_C and k.keycode != KEY_C)
|
||||
or not is_instance_valid(_contract_client)
|
||||
or not _contract_client.has_method("request_issue")
|
||||
):
|
||||
return false
|
||||
if bool(_contract_client.call("is_issue_busy")):
|
||||
return true
|
||||
|
|
@ -274,21 +282,13 @@ func _render_reward_label() -> void:
|
|||
|
||||
|
||||
func _format_issue_deny(reason_code: String) -> String:
|
||||
match reason_code:
|
||||
"active_contract_exists":
|
||||
return "Contract issue: denied — active contract already issued"
|
||||
"no_eligible_template":
|
||||
return "Contract issue: denied — no eligible template (standing/band)"
|
||||
"economy_cap_exceeded":
|
||||
return "Contract issue: denied — economy cap exceeded"
|
||||
"invalid_reward_bundle":
|
||||
return "Contract issue: denied — invalid reward bundle"
|
||||
"unknown_template":
|
||||
return "Contract issue: denied — unknown template"
|
||||
"":
|
||||
return "Contract issue: denied (no reasonCode)"
|
||||
_:
|
||||
return "Contract issue: denied — %s" % reason_code
|
||||
var rc := reason_code.strip_edges()
|
||||
if rc.is_empty():
|
||||
return "Contract issue: denied (no reasonCode)"
|
||||
var copy_variant: Variant = ISSUE_DENY_COPY.get(rc, null)
|
||||
if copy_variant is String:
|
||||
return copy_variant as String
|
||||
return "Contract issue: denied — %s" % rc
|
||||
|
||||
|
||||
func _format_reward_summary_lines(summary: Dictionary) -> PackedStringArray:
|
||||
|
|
@ -325,7 +325,9 @@ func _format_reward_summary_lines(summary: Dictionary) -> PackedStringArray:
|
|||
var amount: int = int(grant.get("amount", 0))
|
||||
if faction_id.is_empty() or amount <= 0:
|
||||
continue
|
||||
lines.append(" %s +%d rep" % [FactionStandingClient.display_name_for(faction_id), amount])
|
||||
lines.append(
|
||||
" %s +%d rep" % [FactionStandingClient.display_name_for(faction_id), amount]
|
||||
)
|
||||
if lines.is_empty():
|
||||
lines.append(" (no grants)")
|
||||
return lines
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
extends RefCounted
|
||||
|
||||
## NEO-153: thin main.gd wiring (keeps main.gd under gdlint max-file-lines).
|
||||
|
||||
const ContractHudController := preload("res://scripts/contract_hud_controller.gd")
|
||||
|
||||
|
||||
static func setup_on(
|
||||
main: Node,
|
||||
hud_root: Node,
|
||||
contract_client: Node,
|
||||
apply_http_config: Callable,
|
||||
item_defs_client: Node = null,
|
||||
inventory_client: Node = null,
|
||||
skill_progression_client: Node = null,
|
||||
faction_standing_client: Node = null
|
||||
) -> Node:
|
||||
var controller: Node = ContractHudController.new()
|
||||
main.add_child(controller)
|
||||
controller.call(
|
||||
"setup",
|
||||
contract_client,
|
||||
hud_root.get_node("ContractActiveLabel"),
|
||||
hud_root.get_node("ContractIssueFeedbackLabel"),
|
||||
hud_root.get_node("ContractRewardDeliveryLabel"),
|
||||
apply_http_config,
|
||||
item_defs_client,
|
||||
inventory_client,
|
||||
skill_progression_client,
|
||||
faction_standing_client
|
||||
)
|
||||
return controller
|
||||
|
||||
|
||||
static func request_refresh(controller: Node) -> void:
|
||||
if is_instance_valid(controller):
|
||||
controller.call("request_contract_refresh")
|
||||
|
||||
|
||||
static func try_issue_key_input(controller: Node, event: InputEvent) -> bool:
|
||||
if not is_instance_valid(controller):
|
||||
return false
|
||||
return bool(controller.call("try_issue_key_input", event))
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bneo153mainwire01
|
||||
|
|
@ -120,3 +120,10 @@ static func _add_prop_visual(
|
|||
prop_mat.albedo_color = Color(0.28, 0.38, 0.45, 1.0)
|
||||
prop_mesh.material_override = prop_mat
|
||||
body.add_child(prop_mesh)
|
||||
|
||||
|
||||
static func set_collision_shapes_disabled(root: Node, disabled: bool) -> void:
|
||||
if root is CollisionShape3D:
|
||||
(root as CollisionShape3D).disabled = disabled
|
||||
for c in root.get_children():
|
||||
set_collision_shapes_disabled(c, disabled)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ const BREACH_GIG_ID := "breach"
|
|||
const PROTOTYPE_ENCOUNTER_ID := "prototype_combat_pocket"
|
||||
const PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS := 3
|
||||
const QuestHudController := preload("res://scripts/quest_hud_controller.gd")
|
||||
const ContractHudController := preload("res://scripts/contract_hud_controller.gd")
|
||||
const ContractHudMainWiring := preload("res://scripts/contract_hud_main_wiring.gd")
|
||||
const InteractableWorldBuilder := preload("res://scripts/interactable_world_builder.gd")
|
||||
|
||||
## Bump on each rejection so older one-shot timers do not clear a newer message.
|
||||
var _move_reject_msg_token: int = 0
|
||||
|
|
@ -139,9 +140,6 @@ var _dev_pulse_bootstrap_attempted: bool = false
|
|||
@onready var _quest_progress_label: Label = _hud_root.get_node("QuestProgressLabel")
|
||||
@onready var _quest_accept_feedback_label: Label = _hud_root.get_node("QuestAcceptFeedbackLabel")
|
||||
@onready var _quest_reward_delivery_label: Label = _hud_root.get_node("QuestRewardDeliveryLabel")
|
||||
@onready var _contract_active_label: Label = _hud_root.get_node("ContractActiveLabel")
|
||||
@onready var _contract_issue_feedback_label: Label = _hud_root.get_node("ContractIssueFeedbackLabel")
|
||||
@onready var _contract_reward_delivery_label: Label = _hud_root.get_node("ContractRewardDeliveryLabel")
|
||||
@onready var _faction_standing_label: Label = _hud_root.get_node("FactionStandingLabel")
|
||||
@onready var _npc_state_label: Label = _hud_root.get_node("NpcStateLabel")
|
||||
@onready var _telegraph_label: Label = _hud_root.get_node("TelegraphLabel")
|
||||
|
|
@ -213,7 +211,16 @@ func _ready() -> void:
|
|||
_setup_gig_progression_sync()
|
||||
_setup_encounter_progress_sync()
|
||||
_setup_quest_progress_sync()
|
||||
_setup_contract_hud()
|
||||
_contract_hud = ContractHudMainWiring.setup_on(
|
||||
self,
|
||||
_hud_root,
|
||||
_contract_client,
|
||||
Callable(self, "_apply_authority_http_config_to_client"),
|
||||
_item_defs_client,
|
||||
_inventory_client,
|
||||
_skill_progression_client,
|
||||
_faction_standing_client
|
||||
)
|
||||
_setup_gather_interact_feedback()
|
||||
_setup_craft_ui()
|
||||
|
||||
|
|
@ -756,7 +763,7 @@ func _on_encounter_progress_received(snapshot: Dictionary) -> void:
|
|||
if str(row.get("state", "")) == "completed":
|
||||
_request_inventory_refresh()
|
||||
_request_quest_progress_refresh()
|
||||
_request_contract_refresh()
|
||||
ContractHudMainWiring.request_refresh(_contract_hud)
|
||||
|
||||
|
||||
func _on_encounter_progress_sync_failed(reason: String) -> void:
|
||||
|
|
@ -893,35 +900,6 @@ func _try_quest_accept_key_input(event: InputEvent) -> bool:
|
|||
return false
|
||||
|
||||
|
||||
func _setup_contract_hud() -> void:
|
||||
# NEO-153: contract issue + progress HUD; boot hydrate + refresh after issue/encounter clear.
|
||||
_contract_hud = ContractHudController.new()
|
||||
add_child(_contract_hud)
|
||||
_contract_hud.call(
|
||||
"setup",
|
||||
_contract_client,
|
||||
_contract_active_label,
|
||||
_contract_issue_feedback_label,
|
||||
_contract_reward_delivery_label,
|
||||
Callable(self, "_apply_authority_http_config_to_client"),
|
||||
_item_defs_client,
|
||||
_inventory_client,
|
||||
_skill_progression_client,
|
||||
_faction_standing_client
|
||||
)
|
||||
|
||||
|
||||
func _request_contract_refresh() -> void:
|
||||
if is_instance_valid(_contract_hud):
|
||||
_contract_hud.call("request_contract_refresh")
|
||||
|
||||
|
||||
func _try_contract_issue_key_input(event: InputEvent) -> bool:
|
||||
if is_instance_valid(_contract_hud):
|
||||
return bool(_contract_hud.call("try_issue_key_input", event))
|
||||
return false
|
||||
|
||||
|
||||
func _render_gather_feedback_label(text: String = "Gather: —") -> void:
|
||||
if is_instance_valid(_gather_feedback_label):
|
||||
_gather_feedback_label.text = text
|
||||
|
|
@ -1374,27 +1352,19 @@ func _render_player_combat_hp_label() -> void:
|
|||
|
||||
func _render_npc_combat_hud_labels() -> void:
|
||||
var rows: Dictionary = _resolve_hud_npc_rows()
|
||||
_render_npc_state_label(rows)
|
||||
_render_telegraph_label(rows)
|
||||
if is_instance_valid(_npc_state_label):
|
||||
_npc_state_label.text = NpcCombatHudHelpers.build_npc_state_label(
|
||||
rows, _npc_runtime_sync_error
|
||||
)
|
||||
if is_instance_valid(_telegraph_label):
|
||||
_telegraph_label.text = NpcCombatHudHelpers.build_telegraph_label(
|
||||
rows, _npc_runtime_hud_state, _npc_runtime_sync_error
|
||||
)
|
||||
_npc_combat_hud_needs_tick = NpcCombatHudHelpers.has_interpolated_telegraph_display(
|
||||
rows, _npc_runtime_hud_state
|
||||
)
|
||||
|
||||
|
||||
func _render_npc_state_label(rows: Dictionary) -> void:
|
||||
if not is_instance_valid(_npc_state_label):
|
||||
return
|
||||
_npc_state_label.text = NpcCombatHudHelpers.build_npc_state_label(rows, _npc_runtime_sync_error)
|
||||
|
||||
|
||||
func _render_telegraph_label(rows: Dictionary) -> void:
|
||||
if not is_instance_valid(_telegraph_label):
|
||||
return
|
||||
_telegraph_label.text = NpcCombatHudHelpers.build_telegraph_label(
|
||||
rows, _npc_runtime_hud_state, _npc_runtime_sync_error
|
||||
)
|
||||
|
||||
|
||||
func _on_move_rejected(reason_code: String) -> void:
|
||||
_authority_force_snap_next = true
|
||||
# Rejected stream: server state may differ; next snap is forced.
|
||||
|
|
@ -1444,7 +1414,7 @@ func _try_route_gameplay_key_input(event: InputEvent) -> bool:
|
|||
return true
|
||||
if _try_quest_accept_key_input(event):
|
||||
return true
|
||||
if _try_contract_issue_key_input(event):
|
||||
if ContractHudMainWiring.try_issue_key_input(_contract_hud, event):
|
||||
return true
|
||||
if _try_inventory_refresh_input(event):
|
||||
return true
|
||||
|
|
@ -1580,7 +1550,7 @@ func _dev_toggle_obstacle_smoke_deferred() -> void:
|
|||
_dev_saved_obstacle_mask = co.collision_mask
|
||||
co.collision_layer = 0
|
||||
co.collision_mask = 0
|
||||
_dev_collision_shapes_set_disabled(obstacle, true)
|
||||
InteractableWorldBuilder.set_collision_shapes_disabled(obstacle, true)
|
||||
obstacle.process_mode = Node.PROCESS_MODE_DISABLED
|
||||
obstacle.visible = false
|
||||
if obstacle.get_parent() == _nav_region:
|
||||
|
|
@ -1594,7 +1564,7 @@ func _dev_toggle_obstacle_smoke_deferred() -> void:
|
|||
if co2 != null and _dev_saved_obstacle_layer >= 0:
|
||||
co2.collision_layer = _dev_saved_obstacle_layer
|
||||
co2.collision_mask = _dev_saved_obstacle_mask
|
||||
_dev_collision_shapes_set_disabled(obstacle, false)
|
||||
InteractableWorldBuilder.set_collision_shapes_disabled(obstacle, false)
|
||||
call_deferred("_dev_rebake_nav_after_obstacle_toggle_deferred")
|
||||
|
||||
|
||||
|
|
@ -1610,28 +1580,19 @@ func _dev_rebake_nav_after_obstacle_toggle_deferred() -> void:
|
|||
_player.sync_navigation_agent_after_map_rebuild(_nav_region)
|
||||
|
||||
|
||||
func _dev_collision_shapes_set_disabled(root: Node, disabled: bool) -> void:
|
||||
if root is CollisionShape3D:
|
||||
(root as CollisionShape3D).disabled = disabled
|
||||
for c in root.get_children():
|
||||
_dev_collision_shapes_set_disabled(c, disabled)
|
||||
|
||||
|
||||
func _on_interactables_catalog_ready(descriptors: Array) -> void:
|
||||
_interactables_catalog = descriptors.duplicate(true)
|
||||
var groups: Variant = load("res://scripts/interactable_world_builder.gd").call(
|
||||
"build_from_catalog", descriptors, _interactables_root, _radius_preview
|
||||
var groups: Variant = InteractableWorldBuilder.build_from_catalog(
|
||||
descriptors, _interactables_root, _radius_preview
|
||||
)
|
||||
if _radius_preview.has_method("setup_glow_groups"):
|
||||
_radius_preview.call("setup_glow_groups", groups as Array)
|
||||
|
||||
|
||||
func _on_interactables_catalog_failed(reason: String) -> void:
|
||||
# `InteractablesCatalogClient` already `push_error`s; this hook exists for wiring clarity.
|
||||
var readme := "Interaction + range preview (NEO-9 + NEO-25)"
|
||||
push_warning(
|
||||
(
|
||||
"Interactables catalog failed (%s) — start the game server first; see client README (%s)."
|
||||
% [reason, readme]
|
||||
"Interactables catalog failed (%s) — start the game server first; see client README."
|
||||
% reason
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
extends GdUnitTestSuite
|
||||
|
||||
## NEO-153: thin main wiring helpers.
|
||||
|
||||
const ContractHudMainWiring := preload("res://scripts/contract_hud_main_wiring.gd")
|
||||
const InteractableWorldBuilder := preload("res://scripts/interactable_world_builder.gd")
|
||||
|
||||
|
||||
func test_try_issue_key_input_returns_false_without_controller() -> void:
|
||||
# Arrange
|
||||
var event := InputEventKey.new()
|
||||
# Act
|
||||
var handled: bool = ContractHudMainWiring.try_issue_key_input(null, event)
|
||||
# Assert
|
||||
assert_bool(handled).is_false()
|
||||
|
||||
|
||||
func test_set_collision_shapes_disabled_recurses_tree() -> void:
|
||||
# Arrange
|
||||
var root := Node3D.new()
|
||||
var shape := CollisionShape3D.new()
|
||||
root.add_child(shape)
|
||||
# Act
|
||||
InteractableWorldBuilder.set_collision_shapes_disabled(root, true)
|
||||
# Assert
|
||||
assert_bool(shape.disabled).is_true()
|
||||
root.free()
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://bneo153mwtest01
|
||||
Loading…
Reference in New Issue