diff --git a/addons/mod_loader/api/log.gd b/addons/mod_loader/api/log.gd index 5df5cb51..cc4b0772 100644 --- a/addons/mod_loader/api/log.gd +++ b/addons/mod_loader/api/log.gd @@ -345,7 +345,8 @@ static func _log(message: String, mod_name: String, log_type: String = "info", o if only_once and _is_logged_before(log_entry): return - _store_log(log_entry) + if ModLoaderStore: + _store_log(log_entry) # Check if the scene_tree is available if Engine.get_main_loop(): @@ -385,6 +386,9 @@ static func _log(message: String, mod_name: String, log_type: String = "info", o static func _is_mod_name_ignored(mod_name: String) -> bool: + if not ModLoaderStore: + return false + var ignored_mod_names := ModLoaderStore.ml_options.ignored_mod_names_in_log as Array if not ignored_mod_names.size() == 0: @@ -394,7 +398,9 @@ static func _is_mod_name_ignored(mod_name: String) -> bool: static func _get_verbosity() -> int: - return ModLoaderStore.ml_options.log_level + if not ModLoaderStore: + return VERBOSITY_LEVEL.DEBUG + return ModLoaderStore.ml_options.log_level static func _store_log(log_entry: ModLoaderLogEntry) -> void: diff --git a/addons/mod_loader/api/profile.gd b/addons/mod_loader/api/profile.gd index 49aed9d0..abac4287 100644 --- a/addons/mod_loader/api/profile.gd +++ b/addons/mod_loader/api/profile.gd @@ -391,7 +391,7 @@ static func _create_new_profile(profile_name: String, mod_list: Dictionary) -> M # If no mods are specified in the mod_list, log a warning and return the new profile if mod_list.keys().size() == 0: - ModLoaderLog.warning("No mod_ids inside \"mod_list\" for user profile \"%s\" " % profile_name, LOG_NAME) + ModLoaderLog.info("No mod_ids inside \"mod_list\" for user profile \"%s\" " % profile_name, LOG_NAME) return new_profile # Set the mod_list diff --git a/addons/mod_loader/internal/file.gd b/addons/mod_loader/internal/file.gd index 0b90fd1b..f336e7e3 100644 --- a/addons/mod_loader/internal/file.gd +++ b/addons/mod_loader/internal/file.gd @@ -51,7 +51,7 @@ static func load_zips_in_folder(folder_path: String) -> Dictionary: var mod_dir := Directory.new() var mod_dir_open_error := mod_dir.open(folder_path) if not mod_dir_open_error == OK: - ModLoaderLog.error("Can't open mod folder %s (Error: %s)" % [folder_path, mod_dir_open_error], LOG_NAME) + ModLoaderLog.info("Can't open mod folder %s (Error: %s)" % [folder_path, mod_dir_open_error], LOG_NAME) return {} var mod_dir_listdir_error := mod_dir.list_dir_begin() if not mod_dir_listdir_error == OK: diff --git a/addons/mod_loader/mod_loader.gd b/addons/mod_loader/mod_loader.gd index edf32143..a0233f72 100644 --- a/addons/mod_loader/mod_loader.gd +++ b/addons/mod_loader/mod_loader.gd @@ -341,7 +341,7 @@ func _init_mod(mod: ModData) -> void: if method.name == "_init": if method.args.size() > 0: argument_found = true - + var mod_main_instance: Node if argument_found: mod_main_instance = mod_main_script.new(self) diff --git a/addons/mod_loader/mod_loader_store.gd b/addons/mod_loader/mod_loader_store.gd index a7a9bc8f..54775ec2 100644 --- a/addons/mod_loader/mod_loader_store.gd +++ b/addons/mod_loader/mod_loader_store.gd @@ -12,7 +12,7 @@ extends Node # Most of these settings should never need to change, aside from the DEBUG_* # options (which should be `false` when distributing compiled PCKs) -const MODLOADER_VERSION = "6.1.0" +const MODLOADER_VERSION = "6.2.0" # If true, a complete array of filepaths is stored for each mod. This is # disabled by default because the operation can be very expensive, but may @@ -150,16 +150,56 @@ func _update_ml_options_from_options_resource() -> void: var ml_options_path := "res://addons/mod_loader/options/options.tres" # Get user options for ModLoader - if _ModLoaderFile.file_exists(ml_options_path): - var options_resource := load(ml_options_path) - if not options_resource.current_options == null: - var current_options: Resource = options_resource.current_options - # Update from the options in the resource - for key in ml_options: - ml_options[key] = current_options[key] - else: + if not _ModLoaderFile.file_exists(ml_options_path): ModLoaderLog.fatal(str("A critical file is missing: ", ml_options_path), LOG_NAME) + var options_resource: ModLoaderCurrentOptions = load(ml_options_path) + if options_resource.current_options == null: + ModLoaderLog.warning(str( + "No current options are set. Falling back to defaults. ", + "Edit your options at %s. " % ml_options_path + ), LOG_NAME) + else: + var current_options = options_resource.current_options + if not current_options is ModLoaderOptionsProfile: + ModLoaderLog.error(str( + "Current options is not a valid Resource of type ModLoaderOptionsProfile. ", + "Please edit your options at %s. " % ml_options_path + ), LOG_NAME) + # Update from the options in the resource + for key in ml_options: + ml_options[key] = current_options[key] + + # Get options overrides by feature tags + # An override is saved as Dictionary[String: ModLoaderOptionsProfile] + for feature_tag in options_resource.feature_override_options.keys(): + if not feature_tag is String: + ModLoaderLog.error(str( + "Options override keys are required to be of type String. Failing key: \"%s.\" " % feature_tag, + "Please edit your options at %s. " % ml_options_path, + "Consult the documentation for all available feature tags: ", + "https://docs.godotengine.org/en/3.5/tutorials/export/feature_tags.html" + ), LOG_NAME) + continue + + if not OS.has_feature(feature_tag): + ModLoaderLog.info("Options override feature tag \"%s\". does not apply, skipping." % feature_tag, LOG_NAME) + continue + + ModLoaderLog.info("Applying options override with feature tag \"%s\"." % feature_tag, LOG_NAME) + var override_options = options_resource.feature_override_options[feature_tag] + if not override_options is ModLoaderOptionsProfile: + ModLoaderLog.error(str( + "Options override is not a valid Resource of type ModLoaderOptionsProfile. ", + "Options override key with invalid resource: \"%s\". " % feature_tag, + "Please edit your options at %s. " % ml_options_path + ), LOG_NAME) + continue + + # Update from the options in the resource + for key in ml_options: + ml_options[key] = override_options[key] + # Update ModLoader's options, via CLI args func _update_ml_options_from_cli_args() -> void: diff --git a/addons/mod_loader/options/options.tres b/addons/mod_loader/options/options.tres index b6a6d85f..01de9f0f 100644 --- a/addons/mod_loader/options/options.tres +++ b/addons/mod_loader/options/options.tres @@ -1,8 +1,12 @@ -[gd_resource type="Resource" load_steps=3 format=2] +[gd_resource type="Resource" load_steps=4 format=2] [ext_resource path="res://addons/mod_loader/options/profiles/current.tres" type="Resource" id=1] [ext_resource path="res://addons/mod_loader/resources/options_current.gd" type="Script" id=2] +[ext_resource path="res://addons/mod_loader/options/profiles/editor.tres" type="Resource" id=3] [resource] script = ExtResource( 2 ) current_options = ExtResource( 1 ) +feature_override_options = { +"editor": ExtResource( 3 ) +} diff --git a/addons/mod_loader/options/profiles/editor.tres b/addons/mod_loader/options/profiles/editor.tres new file mode 100644 index 00000000..d2165c36 --- /dev/null +++ b/addons/mod_loader/options/profiles/editor.tres @@ -0,0 +1,17 @@ +[gd_resource type="Resource" load_steps=2 format=2] + +[ext_resource path="res://addons/mod_loader/resources/options_profile.gd" type="Script" id=1] + +[resource] +script = ExtResource( 1 ) +enable_mods = true +locked_mods = [ ] +log_level = 3 +disabled_mods = [ ] +allow_modloader_autoloads_anywhere = false +steam_workshop_enabled = false +override_path_to_mods = "" +override_path_to_configs = "" +override_path_to_workshop = "" +ignore_deprecated_errors = true +ignored_mod_names_in_log = [ ] diff --git a/addons/mod_loader/resources/options_current.gd b/addons/mod_loader/resources/options_current.gd index f7331f94..5f063493 100644 --- a/addons/mod_loader/resources/options_current.gd +++ b/addons/mod_loader/resources/options_current.gd @@ -1,4 +1,14 @@ class_name ModLoaderCurrentOptions extends Resource -export (Resource) var current_options = null +# The default options set for the mod loader +export (Resource) var current_options: Resource = preload("res://addons/mod_loader/options/profiles/default.tres") + +# Overrides for all available feature tags through OS.has_feature() +# Format: Dictionary[String: ModLoaderOptionsProfile] where the string is a tag +# Warning: Some tags can occur at the same time (Windows + editor for example) - +# In a case where multiple apply, the last one in the dict will override all others +export (Dictionary) var feature_override_options: Dictionary = { + "editor": preload("res://addons/mod_loader/options/profiles/editor.tres") + } +