feat(client): permanent dialogue panel + protocol v13 + build check

- dialogue_box.gd: panel is always visible as permanent insert UI
  element per D-061 — content fades but frame stays on screen
- protocol.gd: bump PROTOCOL_VERSION to 13
- Makefile: add check-protocol target that verifies server/client
  protocol versions match, runs automatically before build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-23 15:36:18 +01:00
co-authored by Claude Opus 4.6
parent eebc151b9f
commit 0880e8d987
3 changed files with 21 additions and 32 deletions
+12 -2
View File
@@ -1,6 +1,6 @@
GODOT := $(shell command -v godot4 2>/dev/null || command -v godot 2>/dev/null)
.PHONY: help setup build client server game stop test lint ci ci-client ci-server clean \
.PHONY: help setup build check-protocol client server game stop test lint ci ci-client ci-server clean \
decisions-sync decisions-coverage decisions-active decisions-orphan \
db-backup db-install validate-content content-ron check-fact-ids setup-hooks \
pre-pr pre-pr-lint pre-pr-build pre-pr-test pre-pr-validate pre-pr-fixtures \
@@ -28,6 +28,7 @@ help:
@echo " make ci Run full CI pipeline locally"
@echo " make ci-client Run client CI checks"
@echo " make ci-server Run server CI checks"
@echo " make check-protocol Verify server/client protocol versions match"
@echo " make clean Remove build artifacts and caches"
@echo ""
@echo " make db-backup Backup shared database to git (main only)"
@@ -82,7 +83,16 @@ setup-hooks:
# --- Build ---
build: build-server build-client
check-protocol:
@SERVER_V=$$(grep 'pub const PROTOCOL_VERSION' server/src/bridge/types.rs | sed 's/.*= *//;s/[^0-9]//g'); \
CLIENT_V=$$(grep 'const PROTOCOL_VERSION' client/scripts/protocol/protocol.gd | sed 's/.*= *//;s/[^0-9]//g'); \
if [ "$$SERVER_V" != "$$CLIENT_V" ]; then \
echo "ERROR: Protocol version mismatch — server=$$SERVER_V, client=$$CLIENT_V"; \
echo " Fix: update client/scripts/protocol/protocol.gd to match server/src/bridge/types.rs"; \
exit 1; \
fi
build: check-protocol build-server build-client
build-server:
cd server && cargo build
+1 -1
View File
@@ -11,7 +11,7 @@ class_name Protocol
## Protocol version — must match server PROTOCOL_VERSION in bridge/types.rs.
## Reject snapshots where version != this value.
const PROTOCOL_VERSION: int = 12
const PROTOCOL_VERSION: int = 13
# -- Decode: bytes from server → GDScript types --------------------------------
+8 -29
View File
@@ -41,7 +41,6 @@ var _option_is_confrontation: Array[bool] = []
var _npc_name: String = ""
# -- UI state --
var _is_showing: bool = false
var _active_tween: Tween = null
var _beat_tween: Tween = null # D-063: confrontation beat delay
@@ -77,9 +76,10 @@ const _WALK_AWAY_ACTIONS: Array[StringName] = [
func _ready() -> void:
panel.modulate.a = 0.0
visible = false
_is_showing = false
# Panel is always visible as a permanent insert UI element (D-061).
# Content fades in/out but the panel frame stays on screen.
visible = true
panel.modulate.a = 1.0
mouse_filter = Control.MOUSE_FILTER_IGNORE
_load_theme()
_update_layout()
@@ -94,8 +94,6 @@ func _process(_delta: float) -> void:
func _unhandled_input(event: InputEvent) -> void:
if not _is_showing:
return
if not _in_player_conversation:
return
@@ -327,25 +325,13 @@ func _end_player_conversation() -> void:
hide_dialogue()
## Hide the entire panel with fade.
## End active dialogue state. Panel stays visible (permanent insert UI element).
func hide_dialogue() -> void:
if not _is_showing:
return
if _in_player_conversation:
_end_player_conversation()
return # _end_player_conversation may call hide_dialogue if log is empty
_is_showing = false
if _active_tween and _active_tween.is_valid():
_active_tween.kill()
_active_tween = create_tween()
_active_tween.tween_property(panel, "modulate:a", 0.0, FADE_OUT)
_active_tween.tween_callback(func():
visible = false
GameState.dialogue_active = false # D-064: unblock movement after fade completes
)
GameState.dialogue_active = false
func is_dialogue_active() -> bool:
@@ -621,16 +607,9 @@ func _expire_entries() -> void:
# -- Visibility --
## Ensure panel is visible (fade in if needed).
## No-op — panel is always visible as a permanent insert UI element.
func _ensure_visible() -> void:
if _is_showing:
return
visible = true
_is_showing = true
if _active_tween and _active_tween.is_valid():
_active_tween.kill()
_active_tween = create_tween()
_active_tween.tween_property(panel, "modulate:a", 1.0, FADE_IN)
pass
func _clear_options() -> void: