Update check: version feed from the git server's releases, title-screen banner, clearer version refusals

This commit is contained in:
Paul Bailey
2026-11-05 16:56:11 +00:00
parent a8eaf0d12e
commit 6ab72f2c05
11 changed files with 446 additions and 4 deletions

View File

@@ -100,6 +100,14 @@ func bind(p: CharacterBody3D) -> void:
tips_row.add_child(again)
_main.add_child(tips_row)
var upd := CheckButton.new()
upd.text = "Check for updates at start (Emberwild %s)" % Updates.version
upd.focus_mode = Control.FOCUS_NONE
upd.button_pressed = Updates.enabled
upd.add_theme_font_size_override("font_size", 16)
upd.toggled.connect(Updates.set_enabled)
_main.add_child(upd)
# The tutorial: skip a step, or leave it (saved, to carry on later).
if Guide.active:
_main.add_child(_button("Skip this tutorial step", func(): Guide.skip(); close()))

View File

@@ -85,6 +85,7 @@ func _ready() -> void:
var spacer := Control.new()
spacer.custom_minimum_size = Vector2(0, 24)
col.add_child(spacer)
_build_update_banner(root)
_pages["main"] = _main_page()
_pages["new"] = _new_page()
@@ -498,7 +499,7 @@ func _on_join_failed(reason: String) -> void:
_on_host_status(reason, true)
return
_join_btn.disabled = false
_join_msg.text = reason
_join_msg.text = reason + version_advice(reason)
_join_msg.add_theme_color_override("font_color", UITheme.BAD)
func _on_left(reason: String) -> void:
@@ -697,3 +698,74 @@ func _play_tutorial() -> void:
func _play(id: String) -> void:
Saves.current_id = id
get_tree().change_scene_to_file(WORLD_SCENE)
# --- updates (scripts/core/updates.gd) ------------------------------------------------
## Asked once per run of the game, not every time you come back to the title.
static var _update_asked := false
var update_banner: PanelContainer
var _update_text: Label
var _update_btn: Button
var version_label: Label
## The version, bottom left; and a card bottom right when a newer one is out.
func _build_update_banner(root: Control) -> void:
version_label = UITheme.label("Emberwild %s" % Updates.version, 13, UITheme.TEXT_DIM)
version_label.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_LEFT)
version_label.offset_left = 16
version_label.offset_top = -30
root.add_child(version_label)
update_banner = UITheme.panel()
update_banner.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_RIGHT)
update_banner.grow_horizontal = Control.GROW_DIRECTION_BEGIN
update_banner.grow_vertical = Control.GROW_DIRECTION_BEGIN
update_banner.offset_right = -24
update_banner.offset_bottom = -24
update_banner.visible = false
root.add_child(update_banner)
var v := VBoxContainer.new()
v.add_theme_constant_override("separation", 8)
v.custom_minimum_size = Vector2(360, 0)
update_banner.add_child(v)
_update_text = UITheme.label("", 16)
_update_text.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
_update_text.custom_minimum_size = Vector2(360, 0)
v.add_child(_update_text)
var h := HBoxContainer.new()
h.add_theme_constant_override("separation", 8)
v.add_child(h)
_update_btn = _button("Download", _on_update_download, 170)
h.add_child(_update_btn)
h.add_child(_button("Not now", func(): update_banner.visible = false, 120))
Updates.checked.connect(_on_update_checked)
if Updates.state == "available":
_on_update_checked("available")
elif not _update_asked:
_update_asked = true
Updates.check()
func _on_update_checked(s: String) -> void:
if s != "available" or update_banner == null:
return
var notes := String(Updates.latest.get("notes", ""))
var how := "" if Updates.packaged() else "\nRunning from the source: git pull in the game folder, then restart."
_update_text.text = "Emberwild %s is out (you have %s).%s%s" % [Updates.latest_version(), Updates.version,
("\n" + notes) if not notes.is_empty() else "", how]
_update_btn.text = "Download" if Updates.packaged() and not String(Updates.download().get("url", "")).is_empty() else "Release page"
_update_btn.disabled = Updates.download_url().is_empty()
update_banner.visible = true
func _on_update_download() -> void:
var u := Updates.download_url()
if not u.is_empty():
OS.shell_open(u)
## Extra words for a "Different game version" refusal: what to do about it.
static func version_advice(reason: String) -> String:
if not reason.begins_with("Different game version"):
return ""
if Updates.state == "available":
return "\nEmberwild %s is out: Download is on the title page." % Updates.latest_version()
if reason.ends_with("Update the game to join."):
return "\nThere's no newer release yet: the server may be running a newer copy from the source."
return ""