187 lines
5.9 KiB
GDScript
187 lines
5.9 KiB
GDScript
@tool
|
|
extends MarginContainer
|
|
###
|
|
# Super-huge thanks to Nathan Hoad and Marcus Skov for ideas and inspiration on how to create a
|
|
# plug-in updater.
|
|
###
|
|
|
|
const TEMP_FILE = "user://update.zip"
|
|
const VERSION_URL: StringName = "https://godotengine.org/asset-library/api/asset/2445"
|
|
|
|
var download_location: String = ""
|
|
var downloading_update: bool = false
|
|
# This will act as both our version checker and update downloader
|
|
var http_request: HTTPRequest = null
|
|
var is_actively_downloading: bool = false
|
|
var new_version: String = ""
|
|
|
|
@onready var cancel_button: Button = %CancelButton
|
|
@onready var downloading: ProgressBar = %Downloading
|
|
@onready var install_button: Button = %InstallButton
|
|
@onready var installed_label: Label = %InstalledLabel
|
|
@onready var update_label: Label = %UpdateLabel
|
|
@onready var update_button: Button = %UpdateButton
|
|
|
|
|
|
func _ready() -> void:
|
|
connect_signals()
|
|
set_defaults()
|
|
check_for_updates()
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
if is_actively_downloading:
|
|
downloading.value = http_request.get_downloaded_bytes() * 100 / http_request.get_body_size()
|
|
|
|
|
|
#region Setup
|
|
func set_defaults() -> void:
|
|
downloading.value = 0
|
|
installed_label.text = "Installed version %s" % Steam.get_godotsteam_version()
|
|
update_button.text = "Up-to-date"
|
|
update_button.disabled = true
|
|
update_label.text = ""
|
|
updating_visibility(false, false, false, true)
|
|
#endregion
|
|
|
|
|
|
#region Signals
|
|
func connect_signals() -> void:
|
|
cancel_button.pressed.connect(_on_cancel_pressed)
|
|
install_button.pressed.connect(_on_install_pressed)
|
|
update_button.pressed.connect(_on_update_pressed)
|
|
#endregion
|
|
|
|
|
|
#region Checking for updates
|
|
func check_for_updates() -> void:
|
|
if not ProjectSettings.get_setting("steam/updates/godotsteam/check_for_updates"):
|
|
return
|
|
|
|
http_request = HTTPRequest.new()
|
|
add_child(http_request)
|
|
http_request.request_completed.connect(_on_http_request_completed)
|
|
if http_request.request(VERSION_URL) != OK:
|
|
printerr("Failed to request GodotSteam plug-in remote current version")
|
|
|
|
|
|
func _on_http_request_completed(result: int, _response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
|
http_request.request_completed.disconnect(_on_http_request_completed)
|
|
http_request.queue_free()
|
|
|
|
if result != HTTPRequest.RESULT_SUCCESS:
|
|
return
|
|
var response = JSON.parse_string(body.get_string_from_utf8())
|
|
if response == null:
|
|
return
|
|
|
|
download_location = response.download_url
|
|
new_version = response.version_string
|
|
|
|
if convert_version(new_version) > convert_version(Steam.get_godotsteam_version()):
|
|
print("New GodotSteam version %s available" % new_version)
|
|
update_label.text = "New version %s" % new_version
|
|
update_button.text = "Download"
|
|
update_button.disabled = false
|
|
#endregion
|
|
|
|
|
|
#region Updating versions
|
|
func _on_cancel_pressed() -> void:
|
|
updating_visibility(false, false, false, true)
|
|
|
|
if is_actively_downloading:
|
|
http_request.cancel_request()
|
|
http_request.queue_free()
|
|
is_actively_downloading = false
|
|
update_label.text = "Canceling %s plug-in update download" % new_version
|
|
else:
|
|
DirAccess.remove_absolute(TEMP_FILE)
|
|
update_label.text = "Canceling %s plug-in update and deleting temporary files" % new_version
|
|
|
|
update_button.text = "Download"
|
|
update_button.disabled = false
|
|
update_label.text = "New version %s" % new_version
|
|
|
|
|
|
func _on_install_pressed() -> void:
|
|
print("Removing older GodotSteam %s plug-in" % Steam.get_godotsteam_version())
|
|
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/godotsteam"))
|
|
|
|
update_button.text = "Unpacking"
|
|
print("Unpacking new %s plug-in" % new_version)
|
|
var zip_reader: ZIPReader = ZIPReader.new()
|
|
zip_reader.open(TEMP_FILE)
|
|
var files: PackedStringArray = zip_reader.get_files()
|
|
|
|
var base_path := files[1]
|
|
# Remove archive folder
|
|
files.remove_at(0)
|
|
# Remove assets folder
|
|
files.remove_at(0)
|
|
|
|
for path in files:
|
|
var new_file_path: String = path.replace(base_path, "")
|
|
if path.ends_with("/"):
|
|
DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path)
|
|
else:
|
|
var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE)
|
|
file.store_buffer(zip_reader.read_file(path))
|
|
|
|
zip_reader.close()
|
|
restart_post_update()
|
|
|
|
|
|
func _on_update_pressed() -> void:
|
|
is_actively_downloading = true
|
|
update_label.text = "Downloading %s plug-in update, please wait" % new_version
|
|
updating_visibility(true, true, false, false)
|
|
|
|
http_request = HTTPRequest.new()
|
|
add_child(http_request)
|
|
http_request.request_completed.connect(_on_download_request_completed)
|
|
if http_request.request(download_location) != OK:
|
|
printerr("Failed to request %s plug-in update download" % new_version)
|
|
is_actively_downloading = false
|
|
update_button.text = "Failed"
|
|
update_button.disabled = false
|
|
return
|
|
|
|
|
|
func _on_download_request_completed(result: int, _response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
|
http_request.request_completed.disconnect(_on_download_request_completed)
|
|
http_request.queue_free()
|
|
is_actively_downloading = false
|
|
updating_visibility(true, false, true, false)
|
|
|
|
if result != HTTPRequest.RESULT_SUCCESS:
|
|
printerr("Failed to download new GodotSteam version %s" % result)
|
|
update_button.disabled = false
|
|
return
|
|
|
|
update_label.text = "Update downloaded, ready to install %s" % new_version
|
|
var zip_file: FileAccess = FileAccess.open(TEMP_FILE, FileAccess.WRITE)
|
|
zip_file.store_buffer(body)
|
|
zip_file.close()
|
|
|
|
|
|
func restart_post_update() -> void:
|
|
update_button.text = "Restarting"
|
|
update_label.text = "Updated to version %s, restarting the editor" % new_version
|
|
DirAccess.remove_absolute(TEMP_FILE)
|
|
EditorInterface.restart_editor(true)
|
|
#endregion
|
|
|
|
|
|
#region Helpers
|
|
func convert_version(version_string: String) -> int:
|
|
return int(version_string.replace(".", "").rpad(4, "0"))
|
|
|
|
|
|
func updating_visibility(cancel: bool, download: bool, install: bool, update: bool) -> void:
|
|
cancel_button.visible = cancel
|
|
downloading.visible = download
|
|
install_button.visible = install
|
|
update_button.visible = update
|
|
#endregion
|