fix(ui): address PR #90 review — 8 items (W1–W4, S5–S6, A3–A4)
W1/A2: add SimBridge.CONNECTED guard before send_input in toggle handler
W2/A1: assert PlatformInfo != null in HardwareDetector._ready();
add ordering comment in project.godot [autoload] section
W3: replace FileAccess.open() with get_file_as_string() in
read_benchmark_cache() — auto-closes, no leak
W4/A3: add _extract_bool_setting() helper in game_state.gd that handles
both {"Bool": true} and plain bool; push_warning on type mismatch
S5: sync _pre_battery_pref from GameState after load_ai_pref() in
HardwareDetector._ready() — closes race if system starts on battery
S6: separate "red" TPT status into its own arm with STATUS_RED dot and
label colour — three-colour mapping: green/yellow/red now distinct
A4: replace DebugConsole.PREFS_PATH compile-time dependency in
_save_ai_pref() with local SETTINGS_CFG_PATH constant
S7 (battery CI guard) already applied by Hoshe in test file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,8 @@ config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
; PlatformInfo MUST remain first — HardwareDetector (and other autoloads) depend on it
|
||||
; being initialised before their own _ready() runs. Do not reorder.
|
||||
PlatformInfo="*res://scripts/autoloads/platform_info.gd"
|
||||
Protocol="*res://scripts/protocol/protocol.gd"
|
||||
SimBridge="*res://scripts/autoloads/sim_bridge.gd"
|
||||
|
||||
@@ -352,8 +352,8 @@ func apply_snapshot(snapshot: Dictionary) -> void:
|
||||
continue
|
||||
if entry.get("key") == "ai_dialogue.enabled":
|
||||
var val: Variant = entry.get("value")
|
||||
if val is Dictionary and val.has("Bool"):
|
||||
ai_enhanced_dialogue_enabled = bool(val["Bool"])
|
||||
if val != null:
|
||||
ai_enhanced_dialogue_enabled = _extract_bool_setting("ai_dialogue.enabled", val)
|
||||
else:
|
||||
settings_response = null
|
||||
|
||||
@@ -403,3 +403,16 @@ func apply_snapshot(snapshot: Dictionary) -> void:
|
||||
boundary_positions[pos] = true
|
||||
elif not has_explicit_positions:
|
||||
visible_positions[pos] = true
|
||||
|
||||
|
||||
# -- Helpers ------------------------------------------------------------------
|
||||
|
||||
## Extract a bool from a tagged-union {"Bool": true} or plain bool value.
|
||||
## Handles both serde encoding styles; emits push_warning on unrecognised format.
|
||||
static func _extract_bool_setting(key: String, val: Variant) -> bool:
|
||||
if val is bool:
|
||||
return val
|
||||
if val is Dictionary and val.has("Bool"):
|
||||
return bool(val["Bool"])
|
||||
push_warning("GameState: unexpected type for setting '%s': %s" % [key, str(val)])
|
||||
return false
|
||||
|
||||
@@ -32,7 +32,9 @@ var _pre_battery_pref: bool = true
|
||||
# -- Lifecycle ----------------------------------------------------------------
|
||||
|
||||
func _ready() -> void:
|
||||
assert(PlatformInfo != null, "PlatformInfo must load before HardwareDetector")
|
||||
load_ai_pref()
|
||||
_pre_battery_pref = GameState.ai_enhanced_dialogue_enabled
|
||||
PlatformInfo.power_profile_changed.connect(_on_power_profile_changed)
|
||||
|
||||
|
||||
@@ -75,11 +77,11 @@ func read_benchmark_cache() -> Variant:
|
||||
var cache_path: String = PlatformInfo.benchmark_cache_path
|
||||
if not FileAccess.file_exists(cache_path):
|
||||
return null
|
||||
var f := FileAccess.open(cache_path, FileAccess.READ)
|
||||
if f == null:
|
||||
var text: String = FileAccess.get_file_as_string(cache_path)
|
||||
if text.is_empty():
|
||||
return null
|
||||
var json := JSON.new()
|
||||
if json.parse(f.get_as_text()) != OK:
|
||||
if json.parse(text) != OK:
|
||||
return null
|
||||
var data: Variant = json.get_data()
|
||||
if not data is Dictionary or not data.has("tps"):
|
||||
|
||||
@@ -16,6 +16,9 @@ const STATUS_RED := Color("#c84040")
|
||||
const FONT_SIZE := 14
|
||||
const FONT_SIZE_SMALL := 11
|
||||
|
||||
## Shared client preferences file — avoids compile-time dependency on DebugConsole for path.
|
||||
const SETTINGS_CFG_PATH := "user://settings.cfg"
|
||||
|
||||
const BOX_WIDTH := 460
|
||||
const BOX_HEIGHT := 500 # +36 debug console, +88 AI dialogue section
|
||||
const PADDING := 20
|
||||
@@ -203,9 +206,9 @@ func _build_ui() -> void:
|
||||
match _ai_hw_status:
|
||||
"pass", "green":
|
||||
status_dot.color = STATUS_GREEN
|
||||
"marginal", "yellow", "red":
|
||||
"marginal", "yellow":
|
||||
status_dot.color = STATUS_YELLOW
|
||||
_: # "fail"
|
||||
_: # "red", "fail"
|
||||
status_dot.color = STATUS_RED
|
||||
ai_hbox.add_child(status_dot)
|
||||
|
||||
@@ -227,9 +230,9 @@ func _build_ui() -> void:
|
||||
ai_status_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
ai_status_label.custom_minimum_size = Vector2(BOX_WIDTH - PADDING * 2, 0)
|
||||
match _ai_hw_status:
|
||||
"marginal", "yellow", "red":
|
||||
"marginal", "yellow":
|
||||
ai_status_label.add_theme_color_override("font_color", STATUS_YELLOW)
|
||||
"fail":
|
||||
"red", "fail":
|
||||
ai_status_label.add_theme_color_override("font_color", STATUS_RED)
|
||||
_:
|
||||
ai_status_label.add_theme_color_override("font_color", TEXT_COLOR)
|
||||
@@ -247,11 +250,12 @@ func _build_ui() -> void:
|
||||
_ai_check_node.toggled.connect(func(enabled: bool) -> void:
|
||||
GameState.ai_enhanced_dialogue_enabled = enabled
|
||||
_save_ai_pref(enabled)
|
||||
SimBridge.send_input({
|
||||
"action": InputMapper.Action.CHANGE_SETTINGS,
|
||||
"action_data": {"ai_enhanced_dialogue": enabled},
|
||||
"timestamp_msec": Time.get_ticks_msec(),
|
||||
})
|
||||
if SimBridge.state == SimBridge.ConnectionState.CONNECTED:
|
||||
SimBridge.send_input({
|
||||
"action": InputMapper.Action.CHANGE_SETTINGS,
|
||||
"action_data": {"ai_enhanced_dialogue": enabled},
|
||||
"timestamp_msec": Time.get_ticks_msec(),
|
||||
})
|
||||
ai_dialogue_toggled.emit(enabled)
|
||||
)
|
||||
|
||||
@@ -335,9 +339,9 @@ func set_ai_inference_suspended(suspended: bool) -> void:
|
||||
## Uses the same settings.cfg as DebugConsole — different section ("ai_dialogue").
|
||||
func _save_ai_pref(enabled: bool) -> void:
|
||||
var cfg := ConfigFile.new()
|
||||
cfg.load(DebugConsole.PREFS_PATH)
|
||||
cfg.load(SETTINGS_CFG_PATH)
|
||||
cfg.set_value("ai_dialogue", "enabled", enabled)
|
||||
cfg.save(DebugConsole.PREFS_PATH)
|
||||
cfg.save(SETTINGS_CFG_PATH)
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
|
||||
Reference in New Issue
Block a user