Files
tekton/launcher/scripts/version_checker.gd
T
2025-12-10 02:35:17 +08:00

141 lines
4.8 KiB
GDScript

extends Node
class_name VersionChecker
## Handles checking for game updates from the version manifest
signal version_check_started
signal version_check_completed(has_update: bool, latest_version: String, changelog: Array)
signal version_check_failed(error: String)
var http_request: HTTPRequest
var current_version: String = "0.0.0"
var latest_version: String = "0.0.0"
var manifest_data: Dictionary = {}
func _ready() -> void:
http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(_on_request_completed)
# Load current local version
_load_local_version()
func _load_local_version() -> void:
if FileAccess.file_exists(Config.LOCAL_VERSION_FILE):
var file := FileAccess.open(Config.LOCAL_VERSION_FILE, FileAccess.READ)
if file:
current_version = file.get_as_text().strip_edges()
file.close()
print("[VersionChecker] Local version: ", current_version)
else:
current_version = "0.0.0"
print("[VersionChecker] No local version found, assuming fresh install")
func check_for_updates() -> void:
emit_signal("version_check_started")
print("[VersionChecker] Checking for updates at: ", Config.VERSION_MANIFEST_URL)
var error := http_request.request(Config.VERSION_MANIFEST_URL)
if error != OK:
emit_signal("version_check_failed", "Failed to initiate version check request")
func _on_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
emit_signal("version_check_failed", "Network error: " + str(result))
return
if response_code != 200:
emit_signal("version_check_failed", "Server returned error: " + str(response_code))
return
var json := JSON.new()
var parse_result := json.parse(body.get_string_from_utf8())
if parse_result != OK:
emit_signal("version_check_failed", "Failed to parse version manifest")
return
manifest_data = json.data
latest_version = manifest_data.get("latest_version", "0.0.0")
var has_update := _compare_versions(current_version, latest_version) < 0
var changelog: Array = _get_changelog_since(current_version)
print("[VersionChecker] Latest version: ", latest_version, " | Has update: ", has_update)
emit_signal("version_check_completed", has_update, latest_version, changelog)
func _compare_versions(v1: String, v2: String) -> int:
## Returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2
var parts1 := v1.split(".")
var parts2 := v2.split(".")
for i in range(max(parts1.size(), parts2.size())):
var p1 := int(parts1[i]) if i < parts1.size() else 0
var p2 := int(parts2[i]) if i < parts2.size() else 0
if p1 < p2:
return -1
elif p1 > p2:
return 1
return 0
func _get_changelog_since(since_version: String) -> Array:
## Get all changelog entries since the given version
var changelog: Array = []
var releases: Array = manifest_data.get("releases", [])
for release in releases:
var release_version: String = release.get("version", "")
if _compare_versions(since_version, release_version) < 0:
changelog.append({
"version": release_version,
"date": release.get("date", ""),
"changes": release.get("changelog", [])
})
return changelog
func get_download_info() -> Dictionary:
## Returns info needed to download the latest version (platform-specific)
var platform := Config.get_platform_name() # "windows", "linux", or "macos"
var releases: Array = manifest_data.get("releases", [])
for release in releases:
if release.get("version") == latest_version:
# Try platform-specific URL first, fall back to generic pck_url
var pck_url: String = ""
var pck_size: int = 0
var checksum_md5: String = ""
var checksum_sha256: String = ""
# Check for platform-specific fields
var platform_key := "pck_" + platform # e.g., "pck_windows", "pck_linux", "pck_macos"
if release.has(platform_key):
var platform_data: Dictionary = release.get(platform_key, {})
pck_url = platform_data.get("url", "")
pck_size = platform_data.get("size", 0)
checksum_md5 = platform_data.get("checksum_md5", "")
checksum_sha256 = platform_data.get("checksum_sha256", "")
else:
# Fall back to generic fields (single PCK for all platforms)
pck_url = release.get("pck_url", "")
pck_size = release.get("pck_size", 0)
checksum_md5 = release.get("checksum_md5", "")
checksum_sha256 = release.get("checksum_sha256", "")
return {
"url": pck_url,
"size": pck_size,
"checksum_md5": checksum_md5,
"checksum_sha256": checksum_sha256
}
return {}
func save_version(version: String) -> void:
## Save the current version to the local version file
var file := FileAccess.open(Config.LOCAL_VERSION_FILE, FileAccess.WRITE)
if file:
file.store_string(version)
file.close()
current_version = version
print("[VersionChecker] Saved version: ", version)