Skip to content

Commit

Permalink
feat: added _remove_extension (#198)
Browse files Browse the repository at this point in the history
* feat: added _reset_extension

* fix: comments and erase saved parent script after resetting

* feat: remove specific mod extension

* fix: remove forgotten log

* style: comment the added code

* fix: add forgotten line to expose script uninstallation

* style: refactor with explicit types and logging style

* style: further refactor for explicit return types
  • Loading branch information
otDan authored Mar 30, 2023
1 parent c0a5624 commit f11fb71
Showing 1 changed file with 68 additions and 13 deletions.
81 changes: 68 additions & 13 deletions addons/mod_loader/mod_loader.gd
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,11 @@ func _apply_extension(extension_path)->Script:
return null

var child_script:Script = ResourceLoader.load(extension_path)
# Adding metadata that contains the extension script path
# We cannot get that path in any other way
# Passing the child_script as is would return the base script path
# Passing the .duplicate() would return a '' path
child_script.set_meta("extension_script_path", extension_path)

# Force Godot to compile the script now.
# We need to do this here to ensure that the inheritance chain is
Expand All @@ -710,43 +715,86 @@ func _apply_extension(extension_path)->Script:
# All the scripts are saved in order already
if not _saved_scripts.has(parent_script_path):
_saved_scripts[parent_script_path] = []
# The first entry in the script path array will be the copy of the base script
# The first entry in the saved script array that has the path
# used as a key will be the duplicate of the not modified script
_saved_scripts[parent_script_path].append(parent_script.duplicate())
_saved_scripts[parent_script_path].append(child_script)
ModLoaderUtils.log_error("base script: %s" % str(_saved_scripts[parent_script_path]), LOG_NAME)

ModLoaderUtils.log_info("Installing script extension: %s <- %s" % [parent_script_path, extension_path], LOG_NAME)
child_script.take_over_path(parent_script_path)

return child_script


# Used to fully reset the provided script to a state prior of any extension
func _reset_extension(parent_script_path: String)->Script:
# Used to remove a specific extension
func _remove_extension(extension_path: String) -> void:
# Check path to file exists
if not File.new().file_exists(parent_script_path):
ModLoaderUtils.log_error("The parent script path '%s' does not exist" % [parent_script_path], LOG_NAME)
if not ModLoaderUtils.file_exists(extension_path):
ModLoaderUtils.log_error("The extension script path \"%s\" does not exist" % [extension_path], LOG_NAME)
return null

var extension_script: Script = ResourceLoader.load(extension_path)
var parent_script: Script = extension_script.get_base_script()
var parent_script_path: String = parent_script.resource_path

# Check if the script to reset has been extended
if not _saved_scripts.has(parent_script_path):
ModLoaderUtils.log_error("The parent script path '%s' has not been extended" % [parent_script_path], LOG_NAME)
return null
ModLoaderUtils.log_error("The extension parent script path \"%s\" has not been extended" % [parent_script_path], LOG_NAME)
return

# Check if the script to reset has anything actually saved
# If we ever encounter this it means something went very wrong in extending
if not _saved_scripts[parent_script_path].size() > 0:
ModLoaderUtils.log_error("The parent script path '%s' does not have the base script saved, this should never happen, if you encounter this please create an issue in the github repository" % [parent_script_path], LOG_NAME)
return null
ModLoaderUtils.log_error("The extension script path \"%s\" does not have the base script saved, this should never happen, if you encounter this please create an issue in the github repository" % [parent_script_path], LOG_NAME)
return

var parent_script_extensions: Array = _saved_scripts[parent_script_path].duplicate()
parent_script_extensions.remove(0)

# Searching for the extension that we want to remove
var found_script_extension: Script = null
for script_extension in parent_script_extensions:
if script_extension.get_meta("extension_script_path") == extension_path:
found_script_extension = script_extension
break

if found_script_extension == null:
ModLoaderUtils.log_error("The extension script path \"%s\" has not been found in the saved extension of the base script" % [parent_script_path], LOG_NAME)
return
parent_script_extensions.erase(found_script_extension)

# Preparing the script to have all other extensions reapllied
_reset_extension(parent_script_path)

var parent_script = _saved_scripts[parent_script_path][0]
# Reapplying all the extensions without the removed one
for script_extension in parent_script_extensions:
_apply_extension(script_extension.get_meta("extension_script_path"))


# Used to fully reset the provided script to a state prior of any extension
func _reset_extension(parent_script_path: String) -> void:
# Check path to file exists
if not ModLoaderUtils.file_exists(parent_script_path):
ModLoaderUtils.log_error("The parent script path \"%s\" does not exist" % [parent_script_path], LOG_NAME)
return

# Check if the script to reset has been extended
if not _saved_scripts.has(parent_script_path):
ModLoaderUtils.log_error("The parent script path \"%s\" has not been extended" % [parent_script_path], LOG_NAME)
return

# Check if the script to reset has anything actually saved
# If we ever encounter this it means something went very wrong in extending
if not _saved_scripts[parent_script_path].size() > 0:
ModLoaderUtils.log_error("The parent script path \"%s\" does not have the base script saved, \nthis should never happen, if you encounter this please create an issue in the github repository" % [parent_script_path], LOG_NAME)
return

var parent_script: Script = _saved_scripts[parent_script_path][0]
parent_script.take_over_path(parent_script_path)

# Remove the script after it has been reset so we do not do it again
_saved_scripts.erase(parent_script_path)

return parent_script


# Helpers
# =============================================================================
Expand All @@ -771,6 +819,13 @@ func install_script_extension(child_script_path:String):
_apply_extension(child_script_path)


func uninstall_script_extension(extension_script_path: String) -> void:

# Currently this is the only thing we do, but it is better to expose
# this function like this for further changes
_remove_extension(extension_script_path)


# Register an array of classes to the global scope, since Godot only does that in the editor.
# Format: { "base": "ParentClass", "class": "ClassName", "language": "GDScript", "path": "res://path/class_name.gd" }
# You can find these easily in the project.godot file under "_global_script_classes"
Expand Down

0 comments on commit f11fb71

Please sign in to comment.