Sets up initial project structure
Initializes the project with core files including: - Editor configuration (.editorconfig, .gitattributes, .gitignore, .vscode/settings.json) - Log.gd addon for enhanced debugging - Loggie addon for advanced logging - Project assets folder
This commit is contained in:
parent
f8140c83ff
commit
02b3be35b0
144 changed files with 7399 additions and 0 deletions
225
addons/loggie/version_management/loggie_version_manager.gd
Normal file
225
addons/loggie/version_management/loggie_version_manager.gd
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
@tool
|
||||
## A class that can be used to inquire about, generate, and operate on [LoggieVersion]s.
|
||||
## It is also responsible for notifying about an available update, and starting it, if configured to do so.
|
||||
class_name LoggieVersionManager extends RefCounted
|
||||
|
||||
## Emitted when this version manager updates the known [member latest_version].
|
||||
signal latest_version_updated()
|
||||
|
||||
## Emitted when this version manager has created a valid [LoggieUpdate] and is ready to use it.
|
||||
signal update_ready()
|
||||
|
||||
## The URL where loggie releases on GitHub can be found.
|
||||
const REMOTE_RELEASES_URL = "https://api.github.com/repos/Shiva-Shadowsong/loggie/releases"
|
||||
|
||||
## The domain from which [LoggieMsg]s from this version manager will be logged from.
|
||||
const REPORTS_DOMAIN : String = "loggie_version_check_reports"
|
||||
|
||||
## Stores the result of reading the Loggie version with [method get_current_Version].
|
||||
var version : LoggieVersion = null
|
||||
|
||||
## Stores the result of reading the latest Loggie version with [method get_latest_version].
|
||||
var latest_version : LoggieVersion = null
|
||||
|
||||
## Stores a reference to a ConfigFile which will be loaded from [member CONFIG_PATH] during [method find_and_store_current_version].
|
||||
var config : ConfigFile = ConfigFile.new()
|
||||
|
||||
## Stores a reference to the logger that's using this version manager.
|
||||
var _logger : Variant = null
|
||||
|
||||
## Stores a reference to the [LoggieUpdate] that has been created to handle an available update.
|
||||
var _update : LoggieUpdate = null
|
||||
|
||||
## Internal debug variable.
|
||||
## If not null, this version manager will treat the [LoggieVersion] provided under this variable to be the current [param version].
|
||||
## Useful for debugging this module when you want to simulate that the current version is something different than it actually is.
|
||||
var _version_proxy : LoggieVersion = null
|
||||
|
||||
## Initializes this version manager, connecting it to the logger that's using it and updating the version cache based on that logger,
|
||||
## which will further prompt the emission of signals in this class, and so on.
|
||||
func connect_logger(logger : Variant) -> void:
|
||||
self.latest_version_updated.connect(on_latest_version_updated)
|
||||
self._logger = logger
|
||||
|
||||
# Set to true during development to enable debug prints related to version management.
|
||||
self._logger.set_domain_enabled(self.REPORTS_DOMAIN, false)
|
||||
|
||||
update_version_cache()
|
||||
|
||||
## Returns a reference to the logger object that is using this version manager.
|
||||
func get_logger() -> Variant:
|
||||
return self._logger
|
||||
|
||||
## Reads the current version of Loggie from plugin.cfg and stores it in [member version].
|
||||
func find_and_store_current_version():
|
||||
var detected_version = self._logger.version
|
||||
if self._version_proxy != null:
|
||||
self.version = self._version_proxy
|
||||
self.version.proxy_for = detected_version
|
||||
else:
|
||||
self.version = detected_version
|
||||
|
||||
## Reads the latest version of Loggie from a GitHub API response and stores it in [member latest_version].
|
||||
func find_and_store_latest_version():
|
||||
var loggie = self.get_logger()
|
||||
var http_request = HTTPRequest.new()
|
||||
loggie.add_child(http_request)
|
||||
loggie.msg("Retrieving version(s) info from endpoint:", REMOTE_RELEASES_URL).domain(REPORTS_DOMAIN).debug()
|
||||
http_request.request_completed.connect(_on_get_latest_version_request_completed, CONNECT_ONE_SHOT)
|
||||
http_request.request(REMOTE_RELEASES_URL)
|
||||
|
||||
## Defines what happens once this version manager emits the signal saying that an update is available.
|
||||
func on_update_available_detected() -> void:
|
||||
var loggie = self.get_logger()
|
||||
if loggie.settings.update_check_mode == LoggieEnums.UpdateCheckType.DONT_CHECK:
|
||||
return
|
||||
|
||||
self._update = LoggieUpdate.new(self.version, self.latest_version)
|
||||
self._update._logger = loggie
|
||||
|
||||
var github_data = self.latest_version.get_meta("github_data")
|
||||
var latest_release_notes_url = github_data.html_url
|
||||
self._update.set_release_notes_url(latest_release_notes_url)
|
||||
loggie.add_child(self._update)
|
||||
update_ready.emit()
|
||||
|
||||
# No plan to allow multiple updates to run during a single Engine session anyway so no need to start another one.
|
||||
# Also, this helps with internal testing of the updater and prevents an updated plugin from auto-starting another update
|
||||
# when dealing with proxy versions.
|
||||
var hasUpdatedAlready = Engine.has_meta("LoggieUpdateSuccessful") and Engine.get_meta("LoggieUpdateSuccessful")
|
||||
|
||||
match loggie.settings.update_check_mode:
|
||||
LoggieEnums.UpdateCheckType.CHECK_AND_SHOW_UPDATER_WINDOW:
|
||||
if hasUpdatedAlready:
|
||||
loggie.info("Update already performed. ✔️")
|
||||
return
|
||||
create_and_show_updater_widget(self._update)
|
||||
LoggieEnums.UpdateCheckType.CHECK_AND_SHOW_MSG:
|
||||
loggie.msg("👀 Loggie update available!").color(Color.ORANGE).header().msg(" > Current version: {version}, Latest version: {latest}".format({
|
||||
"version" : self.version,
|
||||
"latest" : self.latest_version
|
||||
})).info()
|
||||
LoggieEnums.UpdateCheckType.CHECK_DOWNLOAD_AND_SHOW_MSG:
|
||||
if hasUpdatedAlready:
|
||||
loggie.info("Update already performed. ✔️")
|
||||
return
|
||||
loggie.set_domain_enabled("loggie_update_status_reports", true)
|
||||
self._update.try_start()
|
||||
|
||||
## Defines what happens when the request to GitHub API which grabs all the Loggie releases is completed.
|
||||
func _on_get_latest_version_request_completed(result : int, response_code : int, headers : PackedStringArray, body: PackedByteArray):
|
||||
var loggie = self.get_logger()
|
||||
loggie.msg("Response for request received:", response_code).domain(REPORTS_DOMAIN).debug()
|
||||
|
||||
if result != HTTPRequest.RESULT_SUCCESS:
|
||||
return
|
||||
|
||||
var response = JSON.parse_string(body.get_string_from_utf8())
|
||||
|
||||
if typeof(response) != TYPE_ARRAY:
|
||||
loggie.error("The response parsed from GitHub was not an array. Response received in an unsupported format.")
|
||||
return
|
||||
|
||||
var latest_version_data = response[0] # GitHub releases are in order of creation, so grab the first one from the response, that's the latest one.
|
||||
self.latest_version = LoggieVersion.from_string(latest_version_data.tag_name)
|
||||
self.latest_version.set_meta("github_data", latest_version_data)
|
||||
|
||||
loggie.msg("Current version of Loggie:", self.version).msg(" (proxy for: {value})".format({"value": self.version.proxy_for})).domain(REPORTS_DOMAIN).debug()
|
||||
loggie.msg("Latest version of Loggie:", self.latest_version).domain(REPORTS_DOMAIN).debug()
|
||||
latest_version_updated.emit()
|
||||
|
||||
## Executes every time this version manager updates the known latest_version.
|
||||
func on_latest_version_updated() -> void:
|
||||
var loggie = self.get_logger()
|
||||
if loggie == null:
|
||||
return
|
||||
|
||||
# Check if update is available.
|
||||
if loggie.settings.update_check_mode != LoggieEnums.UpdateCheckType.DONT_CHECK:
|
||||
loggie.msg("👀 Loggie:").bold().color("orange").msg(" Checking for updates...").info()
|
||||
if is_update_available():
|
||||
on_update_available_detected()
|
||||
else:
|
||||
loggie.msg("👀 Loggie:").bold().color("orange").msg(" Up to date. ✔️").color(Color.LIGHT_GREEN).info()
|
||||
|
||||
## Displays the widget which informs the user of the available update and offers actions that they can take next.
|
||||
func create_and_show_updater_widget(update : LoggieUpdate) -> Window:
|
||||
const PATH_TO_WIDGET_SCENE = "addons/loggie/version_management/update_prompt_window.tscn"
|
||||
var WIDGET_SCENE = load(PATH_TO_WIDGET_SCENE)
|
||||
if !is_instance_valid(WIDGET_SCENE):
|
||||
push_error("Loggie Update Prompt Window scene not found on expected path: {path}".format({"path": PATH_TO_WIDGET_SCENE}))
|
||||
return
|
||||
|
||||
var loggie = self.get_logger()
|
||||
if loggie == null:
|
||||
return
|
||||
|
||||
var popup_parent = null
|
||||
if Engine.is_editor_hint() and Engine.has_meta("LoggieEditorInterfaceBaseControl"):
|
||||
popup_parent = Engine.get_meta("LoggieEditorInterfaceBaseControl")
|
||||
else:
|
||||
popup_parent = SceneTree.current_scene
|
||||
|
||||
# Configure popup window.
|
||||
var _popup = Window.new()
|
||||
update.succeeded.connect(func():
|
||||
_popup.queue_free()
|
||||
var success_dialog = AcceptDialog.new()
|
||||
var msg = "💬 You may see temporary errors in the console due to Loggie files being re-scanned and reloaded on the spot.\nIt should be safe to dismiss them, but for the best experience, reload the Godot editor (and the plugin, if something seems wrong).\n\n🚩 If you see a 'Files have been modified on disk' window pop up, choose 'Discard local changes and reload' to accept incoming changes."
|
||||
success_dialog.dialog_text = msg
|
||||
success_dialog.title = "Loggie Updater"
|
||||
if is_instance_valid(popup_parent):
|
||||
popup_parent.add_child(success_dialog)
|
||||
success_dialog.popup_centered()
|
||||
)
|
||||
var on_close_requested = func():
|
||||
_popup.queue_free()
|
||||
|
||||
_popup.close_requested.connect(on_close_requested, CONNECT_ONE_SHOT)
|
||||
_popup.borderless = false
|
||||
_popup.unresizable = true
|
||||
_popup.transient = true
|
||||
_popup.title = "Update Available"
|
||||
|
||||
# Configure window widget and add it as a child of the popup window.
|
||||
var widget : LoggieUpdatePrompt = WIDGET_SCENE.instantiate()
|
||||
widget.connect_to_update(update)
|
||||
widget.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
widget._logger = loggie
|
||||
widget.close_requested.connect(on_close_requested, CONNECT_ONE_SHOT)
|
||||
|
||||
if is_instance_valid(popup_parent):
|
||||
popup_parent.add_child(_popup)
|
||||
_popup.popup_centered(widget.host_window_size)
|
||||
_popup.add_child(widget)
|
||||
|
||||
return _popup
|
||||
|
||||
## Updates the local variables which point to the current and latest version of Loggie.
|
||||
func update_version_cache():
|
||||
# Read and cache the current version of Loggie from plugin.cfg.
|
||||
find_and_store_current_version()
|
||||
|
||||
# Read and cache the latest version of Loggie from GitHub.
|
||||
# (Do it only if running in editor, no need for this if running in a game).
|
||||
var logger = self.get_logger()
|
||||
if logger is Node:
|
||||
if !Engine.is_editor_hint():
|
||||
return
|
||||
if logger.is_node_ready():
|
||||
find_and_store_latest_version()
|
||||
else:
|
||||
logger.ready.connect(func():
|
||||
find_and_store_latest_version()
|
||||
, CONNECT_ONE_SHOT)
|
||||
|
||||
## Checks if an update for Loggie is available. Run only after running [method update_version_cache].
|
||||
func is_update_available() -> bool:
|
||||
var loggie = self.get_logger()
|
||||
if !(self.version is LoggieVersion and self.version.is_valid()):
|
||||
loggie.error("The current version of Loggie is not valid. Run `find_and_store_current_version` once to obtain this value first.")
|
||||
return false
|
||||
if !(self.latest_version is LoggieVersion and self.latest_version.is_valid()):
|
||||
loggie.error("The latest version of Loggie is not valid. Run `find_and_store_latest_version` once to obtain this value first.")
|
||||
return false
|
||||
return self.latest_version.is_higher_than(self.version)
|
||||
Loading…
Add table
Add a link
Reference in a new issue