########################################### # CORE Manager # # Developed by the StarOpenSource Project # # Licensed under the GNU General Public # # License version 3 # ########################################### extends Control @onready var action = $Background/Action @onready var path = $Background/Path var path_error = Color.CRIMSON var path_success = Color.LAWN_GREEN var branch = "develop" var versioninfo = {} func _ready() -> void: print("Manager -> Checking operating system") if OS.get_name() == "Windows": path.text = "C:/Path/to/some/project" elif OS.get_name() == "Linux" or OS.get_name() == "macOS" or OS.get_name() == "FreeBSD" or OS.get_name() == "NetBSD" or OS.get_name() == "OpenBSD" or OS.get_name() == "BSD": path.text = "/Path/to/some/project" else: print("Manager -> Invalid operating system detected, exiting.") get_tree().quit(1) return print("Manager -> Checking CORE uac information") check_version() print("Manager -> Initialized.") func check_version() -> void: action.text = "Recieving CORE version information..." action.disabled = true path.editable = false $Background/UpdateUAC.disabled = true var httpr = HTTPRequest.new() httpr.name = "UAC Fetcher" httpr.connect("request_completed",Callable(self,"uac_info")) add_child(httpr) var error = httpr.request("https://fs.staropensource.de/uac/core") if error != OK: print("Manager -> Failed to recieve CORE uac information: HTTPRequest returned code " + str(error)) action.text = "Failed recieving version information (code " + str(error) + ")" func uac_info(_result:int,response:int,_headers:PackedStringArray,body:PackedByteArray) -> void: remove_child(get_children()[1]) if response != 200: print("Manager -> Failed recieving CORE uac information. HTTPRequest returned response code " + str(response)) action.text = "Failed recieving version information (reponse code " + str(response) + ")" action.disabled = true versioninfo = JSON.parse_string(body.get_string_from_utf8()) path.editable = true $Background/UpdateUAC.disabled = false path_changed() func path_changed() -> void: if path.text.contains("\\"): path.add_theme_color_override("font_color",path_error) action.text = "Invalid path. Use / instead of \\." action.disabled = true return if path.text.contains("\n"): path.add_theme_color_override("font_color",path_error) action.text = "Invalid path. Newlines are not allowed." action.disabled = true return if !DirAccess.dir_exists_absolute(path.text) or !FileAccess.file_exists(path.text + "/project.godot"): path.add_theme_color_override("font_color",path_error) action.text = "Does not exist or is no Godot project" action.disabled = true return path.add_theme_color_override("font_color",path_success) check_core() func check_core() -> void: if !DirAccess.dir_exists_absolute(path.text + "/CORE"): action.text = "Install" action.disabled = false return if !FileAccess.file_exists(path.text + "/CORE/.coreinfo"): action.text = "Migrate" action.disabled = false return var info = FileAccess.open(path.text + "/CORE/.coreinfo",FileAccess.READ) var coreinfo = info.get_as_text() info.close() coreinfo = JSON.parse_string(coreinfo) if coreinfo["version"] < versioninfo[branch]["version"]: action.text = "Update" action.disabled = false return elif coreinfo["version"] == versioninfo[branch]["version"]: action.text = "Latest version already installed" action.disabled = true return elif coreinfo["version"] > versioninfo[branch]["version"]: action.text = "You have a future version of CORE... how?" action.disabled = true return action.text = "You should not be seeing this..." action.disabled = true return func install(triggered_by:int) -> bool: print("Manager -> Installing CORE") match(triggered_by): 0: action.text = "Installing CORE..." action.disabled = true path.editable = false $Background/UpdateUAC.disabled = true 1: action.text = "Migrating CORE (updating)..." action.disabled = true path.editable = false $Background/UpdateUAC.disabled = true 2: action.text = "Updating CORE..." action.disabled = true path.editable = false $Background/UpdateUAC.disabled = true _: print("Manager -> Invalid triggered_by value") get_tree().quit(6) DirAccess.make_dir_recursive_absolute(path.text + "/CORE/") var url = versioninfo[branch]["download"] + versioninfo[branch]["commit"] for file in versioninfo[branch]["files"]: var httpr = HTTPRequest.new() httpr.name = "Download " + file httpr.connect("request_completed",Callable(self,"install_file").bind(file,httpr)) add_child(httpr) var error = httpr.request(url + "/" + file) if error != OK: print("Manager -> Failed downloading file \"" + file + "\" (code " + str(error) + ")") action.text = "Failed downloading \"" + file + "\" (code " + str(error) + ")" action.disabled = true return false DirAccess.copy_absolute(path.text + "/CORE/config.gd.example",path.text + "/CORE/config.gd") var file = FileAccess.open(path.text + "/project.godot",FileAccess.READ_WRITE) file.store_string(file.get_as_text() + "\nrun/main_scene=\"res://CORE/coreinit.tscn\"\n[autoload]\nLogger=\"*res://CORE/logger.gd\"\nPreprocessor=\"*res://CORE/preprocessor.gd\"") file.close() file = FileAccess.open(path.text + "/CORE/.coreinfo",FileAccess.WRITE) var file_content = {"version":versioninfo[branch]["version"],"branch":branch,"commit":versioninfo[branch]["commit"]} file.store_string(JSON.stringify(file_content,"\t",true,true)) return true func install_file(_result:int,response:int,_headers:PackedStringArray,body:PackedByteArray,filename:String,httpr:HTTPRequest): print("Manager -> Installing file \"" + filename + "\"") if response != 200: print("Manager -> Failed downloading file \"" + filename + "\" (response code " + str(response) + ")") action.text = "Failed downloading \"" + filename + "\" (response code " + str(response) + ")" action.disabled = true var file = FileAccess.open(path.text + "/CORE/" + filename,FileAccess.WRITE) file.store_buffer(body) file.close() remove_child(httpr) func migrate() -> bool: print("Manager -> Migrating CORE (aka. reinstalling it)") var config = false if FileAccess.file_exists(path.text + "/CORE/config.gd"): config = true DirAccess.copy_absolute(path.text + "/CORE/config.gd",path.text + "/config.gd.bak") DirAccess.remove_absolute(path.text + "/CORE/") if !install(1): return false if config: DirAccess.copy_absolute(path.text + "/config.gd.bak",path.text + "/CORE/config.gd") DirAccess.remove_absolute(path.text + "/config.gd.bak") return true func update() -> bool: print("Manager -> Updating CORE (aka. reinstalling it)") var config = false if FileAccess.file_exists(path.text + "/CORE/config.gd"): config = true DirAccess.copy_absolute(path.text + "/CORE/config.gd",path.text + "/config.gd.bak") DirAccess.remove_absolute(path.text + "/CORE/") if !install(2): return false if config: DirAccess.copy_absolute(path.text + "/config.gd.bak",path.text + "/CORE/config.gd") DirAccess.remove_absolute(path.text + "/config.gd.bak") return true func install_finish(triggered_by:int): match(triggered_by): 0: action.text = "Successfully installed CORE" 1: action.text = "Successfully migrated CORE" 2: action.text = "Successfully updated CORE" _: print("Manager -> Invalid triggered_by value") get_tree().quit(7) func action_press() -> void: match(action.text): "Install": if install(0): install_finish(0) "Migrate": if migrate(): install_finish(1) "Update": if update(): install_finish(2) _: action.disabled = true func _process(_delta) -> void: # Safety check that should never practically be triggered. Still included for the one KDE guy making kwin rules. if DisplayServer.window_get_mode() != Window.MODE_WINDOWED and DisplayServer.window_get_mode() != Window.MODE_MINIMIZED: print("Manager -> Window mode is not WINDOWED or MINIMIZED, setting mode to WINDOWED") DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) DisplayServer.window_set_size(Vector2i(960,540)) @warning_ignore("integer_division") var pos_x = DisplayServer.screen_get_size(DisplayServer.window_get_current_screen()).x/2-DisplayServer.window_get_size().x/2 @warning_ignore("integer_division") var pos_y = DisplayServer.screen_get_size(DisplayServer.window_get_current_screen()).y/2-DisplayServer.window_get_size().y/2 DisplayServer.window_set_position(Vector2i(pos_x,pos_y))