Skip to content

fix: 🐛 fixed missing script parent path #383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion addons/mod_loader/api/mod.gd
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const LOG_NAME := "ModLoader:Mod"
#
# Returns: void
static func install_script_extension(child_script_path: String) -> void:
var mod_id: String = ModLoaderUtils.get_string_in_between(child_script_path, "res://mods-unpacked/", "/")

var mod_id: String = _ModLoaderPath.get_mod_dir(child_script_path)
var mod_data: ModData = get_mod_data(mod_id)
if not ModLoaderStore.saved_extension_paths.has(mod_data.manifest.get_mod_id()):
ModLoaderStore.saved_extension_paths[mod_data.manifest.get_mod_id()] = []
Expand Down
28 changes: 5 additions & 23 deletions addons/mod_loader/internal/mod_loader_utils.gd
Original file line number Diff line number Diff line change
Expand Up @@ -100,30 +100,12 @@ static func _is_valid_global_class_dict(global_class_dict: Dictionary) -> bool:
return true


## Returns the [String] in between two strings in a provided [String]
static func get_string_in_between(string: String, initial: String, ending: String) -> String:
var start_index: int = string.find(initial)
if start_index == -1:
ModLoaderLog.error("Initial string not found.", LOG_NAME)
return ""

start_index += initial.length()

var end_index: int = string.find(ending, start_index)
if end_index == -1:
ModLoaderLog.error("Ending string not found.", LOG_NAME)
return ""
# Deprecated
# =============================================================================

var found_string: String = string.substr(start_index, end_index - start_index)

return found_string


## Deprecated[br]
## =============================================================================[br][br]
## Logs the error in red and a stack trace. Prefixed FATAL-ERROR
## Stops the execution in editor
## Always logged
# Logs the error in red and a stack trace. Prefixed FATAL-ERROR
# Stops the execution in editor
# Always logged
static func log_fatal(message: String, mod_name: String) -> void:
ModLoaderDeprecated.deprecated_changed("ModLoaderUtils.log_fatal", "ModLoaderLog.fatal", "6.0.0")
ModLoaderLog.fatal(message, mod_name)
Expand Down
22 changes: 22 additions & 0 deletions addons/mod_loader/internal/path.gd
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,26 @@ static func get_path_to_mod_configs_dir(mod_id: String) -> String:
static func get_path_to_mod_config_file(mod_id: String, config_name: String) -> String:
var mod_config_dir := get_path_to_mod_configs_dir(mod_id)


return mod_config_dir.path_join(config_name + ".json")


# Returns the mod directory name ("some-mod") from a given path (e.g. "res://mods-unpacked/some-mod/extensions/extension.gd")
static func get_mod_dir(path: String) -> String:
var initial = ModLoaderStore.UNPACKED_DIR
var ending = "/"
var start_index: int = path.find(initial)
if start_index == -1:
ModLoaderLog.error("Initial string not found.", LOG_NAME)
return ""

start_index += initial.length()

var end_index: int = path.find(ending, start_index)
if end_index == -1:
ModLoaderLog.error("Ending string not found.", LOG_NAME)
return ""

var found_string: String = path.substr(start_index, end_index - start_index)

return found_string
27 changes: 23 additions & 4 deletions addons/mod_loader/internal/script_extension.gd
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ static func handle_script_extensions() -> void:
# a script extending script B if A is an ancestor of B.
class InheritanceSorting:
var stack_cache := {}
# This dictionary's keys are mod_ids and it stores the corresponding position in the load_order
var load_order := {}
var unpacked_dir = _ModLoaderPath.get_unpacked_mods_dir_path()

func _init(inheritance_array_to_sort: Array) -> void:
_populate_load_order_table()
inheritance_array_to_sort.sort_custom(check_inheritances)

# Comparator function. return true if a should go before b. This may
Expand All @@ -50,10 +54,10 @@ class InheritanceSorting:
return a_stack[index] < b_stack[index]
last_index = index

if last_index < b_stack.size():
if last_index < b_stack.size() - 1:
return true

return extension_a < extension_b
return compare_mods_order(extension_a, extension_b)

# Returns a list of scripts representing all the ancestors of the extension
# script with the most recent ancestor last.
Expand All @@ -74,14 +78,29 @@ class InheritanceSorting:
stack_cache[extension_path] = stack
return stack

# Secondary comparator function for resolving scripts extending the same vanilla script
# Will return whether a comes before b in the load order
func compare_mods_order(extension_a: String, extension_b: String) -> bool:
var mod_a_id: String = _ModLoaderPath.get_mod_dir(extension_a)
var mod_b_id: String = _ModLoaderPath.get_mod_dir(extension_b)

return load_order[mod_a_id] < load_order[mod_b_id]

# Populate a load order dictionary for faster access and comparison between mod ids
func _populate_load_order_table() -> void:
var mod_index := 0
for mod in ModLoaderStore.mod_load_order:
load_order[mod.dir_name] = mod_index
mod_index += 1


static func apply_extension(extension_path: String) -> Script:
# Check path to file exists
if not FileAccess.file_exists(extension_path):
ModLoaderLog.error("The child script path '%s' does not exist" % [extension_path], LOG_NAME)
return null

var child_script: Script = ResourceLoader.load(extension_path)
var child_script: Script = 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
Expand All @@ -95,7 +114,7 @@ static func apply_extension(extension_path: String) -> Script:
# This is also needed to make Godot instantiate the extended class
# when creating singletons.
# The actual instance is thrown away.
child_script.new()
child_script.reload()

var parent_script: Script = child_script.get_base_script()
var parent_script_path: String = parent_script.resource_path
Expand Down