extends Node class_name VersionChecker const Config = preload("config.gd") ## 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)