143 lines
4.8 KiB
GDScript
143 lines
4.8 KiB
GDScript
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)
|