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

134 lines
4.3 KiB
GDScript

extends Node
class_name DownloadManager
## Handles downloading game files with progress tracking and checksum verification
signal download_started(file_name: String, total_size: int)
signal download_progress(downloaded: int, total: int, percentage: float)
signal download_completed(file_path: String)
signal download_failed(error: String)
var http_request: HTTPRequest
var download_path: String = ""
var expected_checksum_md5: String = ""
var expected_checksum_sha256: String = ""
var total_size: int = 0
var is_downloading: bool = false
func _ready() -> void:
http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(_on_download_completed)
http_request.download_file = "" # We'll set this per download
# Ensure directories exist
_ensure_directories()
func _ensure_directories() -> void:
var dir := DirAccess.open("user://")
if dir:
if not dir.dir_exists("game"):
dir.make_dir("game")
if not dir.dir_exists("backup"):
dir.make_dir("backup")
if not dir.dir_exists("temp"):
dir.make_dir("temp")
func _process(_delta: float) -> void:
if is_downloading and http_request:
var downloaded := http_request.get_downloaded_bytes()
var body_size := http_request.get_body_size()
if body_size > 0:
var percentage := (float(downloaded) / float(body_size)) * 100.0
emit_signal("download_progress", downloaded, body_size, percentage)
func download_file(url: String, file_name: String, size: int = 0, md5: String = "", sha256: String = "") -> void:
if is_downloading:
emit_signal("download_failed", "Download already in progress")
return
download_path = "user://temp/" + file_name
expected_checksum_md5 = md5
expected_checksum_sha256 = sha256
total_size = size
is_downloading = true
# Set download file path
http_request.download_file = download_path
print("[DownloadManager] Starting download: ", url)
print("[DownloadManager] Saving to: ", download_path)
emit_signal("download_started", file_name, size)
var error := http_request.request(url)
if error != OK:
is_downloading = false
emit_signal("download_failed", "Failed to initiate download: " + str(error))
func _on_download_completed(result: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray) -> void:
is_downloading = false
if result != HTTPRequest.RESULT_SUCCESS:
emit_signal("download_failed", "Download failed with result: " + str(result))
return
if response_code != 200:
emit_signal("download_failed", "Server returned error: " + str(response_code))
return
# Verify checksum if provided
if expected_checksum_md5 != "" or expected_checksum_sha256 != "":
if not _verify_checksum():
emit_signal("download_failed", "Checksum verification failed - file may be corrupted")
# Delete corrupted file
var dir := DirAccess.open("user://temp/")
if dir:
dir.remove(download_path.get_file())
return
print("[DownloadManager] Download completed: ", download_path)
emit_signal("download_completed", download_path)
func _verify_checksum() -> bool:
## Verify the downloaded file's checksum
var file := FileAccess.open(download_path, FileAccess.READ)
if not file:
print("[DownloadManager] Could not open file for checksum verification")
return false
var content := file.get_buffer(file.get_length())
file.close()
# Verify MD5 if provided
if expected_checksum_md5 != "":
var ctx := HashingContext.new()
ctx.start(HashingContext.HASH_MD5)
ctx.update(content)
var calculated_md5 := ctx.finish().hex_encode()
if calculated_md5.to_lower() != expected_checksum_md5.to_lower():
print("[DownloadManager] MD5 mismatch! Expected: ", expected_checksum_md5, " Got: ", calculated_md5)
return false
print("[DownloadManager] MD5 checksum verified")
# Verify SHA256 if provided
if expected_checksum_sha256 != "":
var ctx := HashingContext.new()
ctx.start(HashingContext.HASH_SHA256)
ctx.update(content)
var calculated_sha256 := ctx.finish().hex_encode()
if calculated_sha256.to_lower() != expected_checksum_sha256.to_lower():
print("[DownloadManager] SHA256 mismatch! Expected: ", expected_checksum_sha256, " Got: ", calculated_sha256)
return false
print("[DownloadManager] SHA256 checksum verified")
return true
func cancel_download() -> void:
if is_downloading:
http_request.cancel_request()
is_downloading = false
print("[DownloadManager] Download cancelled")