current_schema_version() line-scanned res://../project.yaml at runtime. That resolves to the repo root in a dev run and to nothing in an exported build, so a shipped game got the "?.?.?" fallback every time. Since that tag is the Atlas disk cache's ONLY invalidation signal, every exported build stamped and compared the same sentinel: a canvas cached by one build would be served by every later build, forever. T-1239 is what that failure looks like once it happens. loading_screen.gd carried a byte-for-byte copy of the same function, so the version shown to the player was "?.?.?" in exactly the builds where a version string is worth showing. Both call sites now share client/scripts/build_version.gd, which reads application/config/version out of ProjectSettings — a value Godot bakes into the PCK, identical in the editor and in an export by construction rather than by luck. No file IO, no fallback branch. project.yaml stays the source of truth (CLAUDE.md); client/project.godot mirrors it. A mirror nobody checks would be worse than the bug it replaces -- the old code failed loudly everywhere, a stale mirror fails silently -- so tooling/check-client-version compares the two and the pre-push hook runs it unconditionally. Not gated on "were those files in this push": drift persists on main once introduced, and gating would let an existing drift ride along. The test this replaces asserted that current_schema_version() did not return its fallback, and passed -- in the one environment where the code under test worked. Three tests now pin the property that actually matters: a real version, sourced from the baked setting, matching project.yaml. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
91 lines
3.3 KiB
GDScript
91 lines
3.3 KiB
GDScript
extends MetaScreen
|
|
## #257: Loading screen overlay — blocks input during save/load round-trip.
|
|
## Shown when LOAD_GAME fires; hidden when save_result arrives (success or failure).
|
|
## Full-screen, dark overlay with centered status text.
|
|
## #724: Shows client version and protocol version below the status text. The
|
|
## version comes from ProjectSettings (mirrored from project.yaml) so it survives
|
|
## an export — see build_version.gd (T-1241).
|
|
|
|
const BuildVersion := preload("res://scripts/build_version.gd")
|
|
|
|
const BG_COLOR := Color(0.05, 0.05, 0.08, 1.0)
|
|
const TEXT_COLOR := Color("#c8d0e0")
|
|
const VERSION_COLOR := Color("#667788")
|
|
const FONT_SIZE := 18
|
|
const VERSION_FONT_SIZE := 11
|
|
|
|
var _label: Label = null
|
|
var _version_label: Label = null
|
|
|
|
|
|
func _ready() -> void:
|
|
closable_by_escape = false
|
|
visible = false
|
|
mouse_filter = Control.MOUSE_FILTER_STOP
|
|
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
_build_ui()
|
|
|
|
|
|
func _build_ui() -> void:
|
|
var bg := ColorRect.new()
|
|
bg.color = BG_COLOR
|
|
bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(bg)
|
|
|
|
_label = Label.new()
|
|
_label.text = UIStrings.get_text("notifications.loading")
|
|
_label.add_theme_font_size_override("font_size", FONT_SIZE)
|
|
_label.add_theme_color_override("font_color", TEXT_COLOR)
|
|
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
_label.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(_label)
|
|
|
|
var client_ver := _read_client_version()
|
|
_version_label = Label.new()
|
|
_version_label.text = "v%s" % [client_ver]
|
|
_version_label.add_theme_font_size_override("font_size", VERSION_FONT_SIZE)
|
|
_version_label.add_theme_color_override("font_color", VERSION_COLOR)
|
|
_version_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
_version_label.anchor_left = 0.0
|
|
_version_label.anchor_right = 1.0
|
|
_version_label.anchor_top = 1.0
|
|
_version_label.anchor_bottom = 1.0
|
|
_version_label.offset_top = -32.0
|
|
_version_label.offset_bottom = -8.0
|
|
_version_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(_version_label)
|
|
|
|
|
|
## T-1241: was a byte-for-byte copy of the disk cache's own project.yaml scan,
|
|
## with the same export defect — a shipped build has no res://../project.yaml, so
|
|
## the version shown to the player read "?.?.?" in exactly the builds where a
|
|
## version string is worth showing. Both call sites now share build_version.gd.
|
|
##
|
|
## The display fallback stays HERE rather than in the accessor: BuildVersion
|
|
## returns "" for a missing setting and does not invent a value, because its
|
|
## other caller keys cache invalidation on it and a plausible-looking sentinel
|
|
## there is what made this bug survive. A label, unlike a cache key, still has to
|
|
## render something, so it substitutes its own.
|
|
func _read_client_version() -> String:
|
|
var v := BuildVersion.current()
|
|
return v if not v.is_empty() else "?.?.?"
|
|
|
|
|
|
## Update the status text shown while loading. Call before show_loading() or after.
|
|
func set_message(text: String) -> void:
|
|
if _label != null:
|
|
_label.text = text
|
|
|
|
|
|
func show_loading() -> void:
|
|
MetaStack.push(self)
|
|
open()
|
|
|
|
|
|
## Hide the loading overlay. success=false is reserved for future failure-state UI.
|
|
func hide_loading(_success: bool = true) -> void:
|
|
close()
|