Files
settled-reach/client/scripts/main.gd
T
jpmschweitzerandClaude Opus 4.6 9e8ccb13bf fix(client): address PR #22 review — 3 critical bugs, 2 warnings, 8 suggestions
Critical fixes:
- fog_state: guard _compute_bounds() against all-invalid tiles (negative Rect2i crash)
- fog_shader: read Camera2D zoom dynamically instead of hardcoded Vector2(2,2)
- world_radial: set custom_minimum_size in _ready() from spoke geometry

Warnings:
- fog.gdshader: tighten PERIPHERAL_LOW 0.15→0.55 to match D-059 peripheral band
- Extract color_for_entity_kind() to Constants.gd, decouple CursorRenderer from EntityRenderer

Documentation: shallow copy assumption, gradual decay TODO, tween guard rationale,
fade timing rationale, ToggleInsert TODO, monologue consume-once, hover offset safety,
v6 fixture gap TODO.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 23:23:11 +01:00

79 lines
3.1 KiB
GDScript

extends Node2D
@onready var world_renderer = $World
@onready var camera = $Camera2D
@onready var hud = $UILayer/HUD
@onready var monologue_display = $UILayer/MonologueDisplay
@onready var interaction_prompt = $InsertOverlay/InteractionPrompt # v0.1 single-line fallback
@onready var interaction_list = $InsertOverlay/InteractionList # D-057: z-layer 6
@onready var world_radial = $InsertOverlay/WorldRadial # D-058: z-layer 6
@onready var inventory_grid = $UILayer/InventoryGrid # D-065: z-layer 7
@onready var stance_indicator = $UILayer/StanceIndicator # D-053: z-layer 7
@onready var cursor_renderer = $UILayer/CursorRenderer # D-056: z-layer 7
func _ready() -> void:
print("The Settled Reach — client initialized")
# Connect to simulation (will use test mode initially)
SimBridge.connect_to_sim()
func _process(_delta: float) -> void:
# Main game loop: poll snapshot, apply state, flush input
var snapshot = SimBridge.poll_snapshot()
if snapshot != null:
GameState.apply_snapshot(snapshot)
# Update renderers with new state
if world_renderer and world_renderer.has_method("update_from_state"):
world_renderer.update_from_state()
# D-057: Update interaction list from game state
if interaction_list and interaction_list.has_method("update_from_state"):
interaction_list.update_from_state()
# D-065: Update inventory grid
if inventory_grid and inventory_grid.has_method("update_from_state"):
inventory_grid.update_from_state()
# D-053: Update stance indicator
if stance_indicator and stance_indicator.has_method("update_from_state"):
stance_indicator.update_from_state()
# Show monologue if server sent one this tick (#414)
# Consume-once: set to null after showing to prevent re-display.
# Single monologue per snapshot is guaranteed by server.
if GameState.current_monologue != null and monologue_display:
var mono: Dictionary = GameState.current_monologue
monologue_display.show_monologue(mono.get("text", ""), mono.get("duration_seconds", 5.0))
GameState.current_monologue = null
# Track camera to player position every frame (D-015: locked, no panning)
# Camera2D smoothing handles interpolation — we just set the target
camera.global_position = GameState.player_position * Constants.TILE_SIZE
# Send queued input to simulation
var inputs = InputMapper.flush_queue()
for input in inputs:
if input.action == InputMapper.Action.INTERACT:
# D-057: prefer interaction list (multi-verb), fall back to prompt (v0.1)
var target_id: int = -1
var verb: String = ""
if interaction_list and interaction_list.has_method("get_interaction_target"):
target_id = interaction_list.get_interaction_target()
verb = interaction_list.get_selected_verb()
if target_id < 0 and interaction_prompt:
target_id = interaction_prompt.get_interaction_target()
verb = interaction_prompt.get_selected_verb()
# Always send struct form for Interact (#415) — server expects named fields
if target_id >= 0:
input["action_data"] = {
"target_entity_id": target_id,
"verb": verb,
}
else:
input["action_data"] = {
"target_entity_id": null,
"verb": null,
}
SimBridge.send_input(input)