init
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
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")
|
||||
Reference in New Issue
Block a user