Skip to content
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

Split off logging and utils #62

Merged
merged 4 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions addons/mod_loader/mod_data.gd
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ func load_manifest() -> void:
if not has_required_files():
return

# ModLoader.mod_log("Loading mod_manifest (manifest.json) for -> %s" % dir_name, LOG_NAME)
ModLoaderUtils.log_info("Loading mod_manifest (manifest.json) for -> %s" % dir_name, LOG_NAME)

# Load meta data file
var manifest_path = get_required_mod_file_path(required_mod_files.MANIFEST)
var manifest_dict = _get_json_as_dict(manifest_path) # todo get from utils

# ModLoader.mod_log("%s loaded manifest data -> %s" % [dir_name, manifest_dict], LOG_NAME)
ModLoaderUtils.log_info("%s loaded manifest data -> %s" % [dir_name, manifest_dict], LOG_NAME)

var mod_manifest := ModManifest.new(manifest_dict)

Expand All @@ -61,7 +61,7 @@ func load_manifest() -> void:
func is_mod_dir_name_same_as_id() -> bool:
var manifest_id = manifest.get_mod_id()
if dir_name != manifest_id:
# ModLoader.mod_log('ERROR - Mod directory name "%s" does not match the data in manifest.json. Expected "%s"' % [ dir_name, manifest_id ], LOG_NAME)
ModLoaderUtils.log_fatal('Mod directory name "%s" does not match the data in manifest.json. Expected "%s"' % [ dir_name, manifest_id ], LOG_NAME)
is_loadable = false
return false
return true
Expand All @@ -75,7 +75,7 @@ func has_required_files() -> bool:
var file_path = get_required_mod_file_path(required_mod_files[required_file])

if !file_check.file_exists(file_path):
# ModLoader.mod_log("ERROR - %s is missing a required file: %s" % [dir_name, file_path], LOG_NAME)
ModLoaderUtils.log_fatal("ERROR - %s is missing a required file: %s" % [dir_name, file_path], LOG_NAME)
is_loadable = false
return is_loadable

Expand Down
131 changes: 39 additions & 92 deletions addons/mod_loader/mod_loader.gd
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ extends Node
# Most of these settings should never need to change, aside from the DEBUG_*
# options (which should be `false` when distributing compiled PCKs)

# Enables logging messages made with dev_log. Usually these are enabled with the
# command line arg `--log-dev`, but you can also enable them this way if you're
# debugging in the editor
const DEBUG_ENABLE_DEV_LOG = false

# 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
# be useful for debugging
Expand Down Expand Up @@ -90,24 +85,24 @@ func _init():
return

# Log game install dir
mod_log(str("game_install_directory: ", _get_local_folder_dir()), LOG_NAME)
ModLoaderUtils.log_info(str("game_install_directory: ", _get_local_folder_dir()), LOG_NAME)

# check if we want to use a different mods path that is provided as a command line argument
var cmd_line_mod_path = _get_cmd_line_arg("--mods-path")
if cmd_line_mod_path != "":
os_mods_path_override = cmd_line_mod_path
mod_log("The path mods are loaded from has been changed via the CLI arg `--mods-path`, to: " + cmd_line_mod_path, LOG_NAME)
ModLoaderUtils.log_info("The path mods are loaded from has been changed via the CLI arg `--mods-path`, to: " + cmd_line_mod_path, LOG_NAME)

# Check for the CLI arg that overrides the configs path
var cmd_line_configs_path = _get_cmd_line_arg("--configs-path")
if cmd_line_configs_path != "":
os_configs_path_override = cmd_line_configs_path
mod_log("The path configs are loaded from has been changed via the CLI arg `--configs-path`, to: " + cmd_line_configs_path, LOG_NAME)
ModLoaderUtils.log_info("The path configs are loaded from has been changed via the CLI arg `--configs-path`, to: " + cmd_line_configs_path, LOG_NAME)

# Loop over "res://mods" and add any mod zips to the unpacked virtual
# directory (UNPACKED_DIR)
_load_mod_zips()
mod_log("DONE: Loaded all mod files into the virtual filesystem", LOG_NAME)
ModLoaderUtils.log_success("DONE: Loaded all mod files into the virtual filesystem", LOG_NAME)

# Loop over UNPACKED_DIR. This triggers _init_mod_data for each mod
# directory, which adds their data to mod_data.
Expand All @@ -125,7 +120,7 @@ func _init():
var mod: ModData = mod_data[dir_name]
mod.load_manifest()

mod_log("DONE: Loaded all meta data", LOG_NAME)
ModLoaderUtils.log_success("DONE: Loaded all meta data", LOG_NAME)

# Run dependency checks after loading mod_manifest. If a mod depends on another
# mod that hasn't been loaded, that dependent mod won't be loaded.
Expand All @@ -142,61 +137,17 @@ func _init():
var mod_i = 1
for mod in mod_load_order: # mod === mod_data
mod = mod as ModData
dev_log("mod_load_order -> %s) %s" % [mod_i, mod.dir_name], LOG_NAME)
ModLoaderUtils.log_debug("mod_load_order -> %s) %s" % [mod_i, mod.dir_name], LOG_NAME)
mod_i += 1

# Instance every mod and add it as a node to the Mod Loader
for mod in mod_load_order:
# mod_log(str("Initializing -> ", mod.mod_manifest.extra.godot.id), LOG_NAME)
mod_log("Initializing -> %s" % mod.manifest.get_mod_id(), LOG_NAME)
ModLoaderUtils.log_info("Initializing -> %s" % mod.manifest.get_mod_id(), LOG_NAME)
_init_mod(mod)

dev_log(str("mod_data: ", JSON.print(mod_data, ' ')), LOG_NAME)

mod_log("DONE: Completely finished loading mods", LOG_NAME)


# Log developer info. Has to be enabled, either with the command line arg
# `--log-dev`, or by temporarily enabling DEBUG_ENABLE_DEV_LOG
func dev_log(text:String, mod_name:String = "Unknown-Mod", pretty:bool = false):
if DEBUG_ENABLE_DEV_LOG || (_check_cmd_line_arg("--log-dev")):
mod_log(text, mod_name, pretty)


# Log info for a mod. Accepts the mod name as the 2nd arg, which prefixes
# the logged string with "{mod_name}: "
func mod_log(text:String, mod_name:String = "Unknown-Mod", pretty:bool = false)->void:
# Prefix with "{mod_name}: "
var prefix = mod_name + ": "

var date_time = Time.get_datetime_dict_from_system()
ModLoaderUtils.log_debug_json_print("mod data", mod_data, LOG_NAME)

# Add leading zeroes if needed
var hour := (date_time.hour as String).pad_zeros(2)
var mins := (date_time.minute as String).pad_zeros(2)
var secs := (date_time.second as String).pad_zeros(2)

var date_time_string := "%s.%s.%s - %s:%s:%s" % [date_time.day, date_time.month, date_time.year, hour, mins, secs]

print(str(date_time_string,' ', prefix, text))

var log_file = File.new()

if(!log_file.file_exists(MOD_LOG_PATH)):
log_file.open(MOD_LOG_PATH, File.WRITE)
log_file.store_string('%s Created mod.log!' % date_time_string)
log_file.close()

var _error = log_file.open(MOD_LOG_PATH, File.READ_WRITE)
if _error:
print(_error)
return
log_file.seek_end()
if pretty:
log_file.store_string("\n" + str(date_time_string,' ', prefix, JSON.print(text, " ")))
else:
log_file.store_string("\n" + str(date_time_string,' ', prefix, text))
log_file.close()
ModLoaderUtils.log_success("DONE: Completely finished loading mods", LOG_NAME)


# Loop over "res://mods" and add any mod zips to the unpacked virtual directory
Expand All @@ -207,10 +158,10 @@ func _load_mod_zips():

var dir = Directory.new()
if dir.open(game_mod_folder_path) != OK:
mod_log("Can't open mod folder %s." % game_mod_folder_path, LOG_NAME)
ModLoaderUtils.log_error("Can't open mod folder %s." % game_mod_folder_path, LOG_NAME)
return
if dir.list_dir_begin() != OK:
mod_log("Can't read mod folder %s." % game_mod_folder_path, LOG_NAME)
ModLoaderUtils.log_error("Can't read mod folder %s." % game_mod_folder_path, LOG_NAME)
return

var has_shown_editor_warning = false
Expand Down Expand Up @@ -246,22 +197,22 @@ func _load_mod_zips():
# https://github.com/godotengine/godot/issues/19815
# https://github.com/godotengine/godot/issues/16798
if OS.has_feature("editor") && !has_shown_editor_warning:
mod_log(str(
"WARNING: Loading any resource packs (.zip/.pck) with `load_resource_pack` will WIPE the entire virtual res:// directory. ",
ModLoaderUtils.log_warning(str(
"Loading any resource packs (.zip/.pck) with `load_resource_pack` will WIPE the entire virtual res:// directory. ",
"If you have any unpacked mods in ", UNPACKED_DIR, ", they will not be loaded. ",
"Please unpack your mod ZIPs instead, and add them to ", UNPACKED_DIR), LOG_NAME)
has_shown_editor_warning = true

dev_log(str("Found mod ZIP: ", mod_folder_global_path), LOG_NAME)
ModLoaderUtils.log_debug(str("Found mod ZIP: ", mod_folder_global_path), LOG_NAME)

# If there was an error loading the mod zip file
if !is_mod_loaded_success:
# Log the error and continue with the next file
mod_log(str(mod_zip_file_name, " failed to load."), LOG_NAME)
ModLoaderUtils.log_error(str(mod_zip_file_name, " failed to load."), LOG_NAME)
continue

# Mod successfully loaded!
mod_log(str(mod_zip_file_name, " loaded."), LOG_NAME)
ModLoaderUtils.log_success(str(mod_zip_file_name, " loaded."), LOG_NAME)

dir.list_dir_end()

Expand All @@ -274,10 +225,10 @@ func _setup_mods():

var dir = Directory.new()
if dir.open(unpacked_mods_path) != OK:
mod_log("Can't open unpacked mods folder %s." % unpacked_mods_path, LOG_NAME)
ModLoaderUtils.log_error("Can't open unpacked mods folder %s." % unpacked_mods_path, LOG_NAME)
return
if dir.list_dir_begin() != OK:
mod_log("Can't read unpacked mods folder %s." % unpacked_mods_path, LOG_NAME)
ModLoaderUtils.log_error("Can't read unpacked mods folder %s." % unpacked_mods_path, LOG_NAME)
return

# Get all unpacked mod dirs
Expand Down Expand Up @@ -317,13 +268,13 @@ func _load_mod_configs():
var json_path = configs_path.plus_file(dir_name + ".json")
var mod_config = ModData._get_json_as_dict(json_path)

dev_log(str("Config JSON: Looking for config at path: ", json_path), LOG_NAME)
ModLoaderUtils.log_debug(str("Config JSON: Looking for config at path: ", json_path), LOG_NAME)

if mod_config.size() > 0:
found_configs_count += 1

mod_log(str("Config JSON: Found a config file: '", json_path, "'"), LOG_NAME)
dev_log(str("Config JSON: File data: ", JSON.print(mod_config)), LOG_NAME)
ModLoaderUtils.log_info(str("Config JSON: Found a config file: '", json_path, "'"), LOG_NAME)
ModLoaderUtils.log_debug(str("Config JSON: File data: ", JSON.print(mod_config)), LOG_NAME)

# Check `load_from` option. This lets you specify the name of a
# different JSON file to load your config from. Must be in the same
Expand All @@ -333,21 +284,21 @@ func _load_mod_configs():
if mod_config.has("load_from"):
var new_path = mod_config.load_from
if new_path != "" && new_path != str(dir_name, ".json"):
mod_log(str("Config JSON: Following load_from path: ", new_path), LOG_NAME)
ModLoaderUtils.log_info(str("Config JSON: Following load_from path: ", new_path), LOG_NAME)
var new_config = ModData._get_json_as_dict(configs_path + new_path)
if new_config.size() > 0 != null:
mod_config = new_config
mod_log(str("Config JSON: Loaded from custom json: ", new_path), LOG_NAME)
dev_log(str("Config JSON: File data: ", JSON.print(mod_config)), LOG_NAME)
ModLoaderUtils.log_info(str("Config JSON: Loaded from custom json: ", new_path), LOG_NAME)
ModLoaderUtils.log_debug(str("Config JSON: File data: ", JSON.print(mod_config)), LOG_NAME)
else:
mod_log(str("Config JSON: ERROR - Could not load data via `load_from` for ", dir_name, ", at path: ", new_path), LOG_NAME)
ModLoaderUtils.log_error(str("Config JSON: ERROR - Could not load data via `load_from` for ", dir_name, ", at path: ", new_path), LOG_NAME)

mod_data[dir_name].config = mod_config

if found_configs_count > 0:
mod_log(str("Config JSON: Loaded ", str(found_configs_count), " config(s)"), LOG_NAME)
ModLoaderUtils.log_success(str("Config JSON: Loaded ", str(found_configs_count), " config(s)"), LOG_NAME)
else:
mod_log(str("Config JSON: No mod configs were found"), LOG_NAME)
ModLoaderUtils.log_info(str("Config JSON: No mod configs were found"), LOG_NAME)


# Add a mod's data to mod_data.
Expand Down Expand Up @@ -376,7 +327,7 @@ func _init_mod_data(mod_folder_path):
# mod_manifest (ie. its manifest.json file). If a mod depends on another mod that
# hasn't been loaded, the dependent mod won't be loaded.
func _check_dependencies(mod_id:String, deps:Array):
dev_log(str("Checking dependencies - mod_id: ", mod_id, " dependencies: ", deps), LOG_NAME)
ModLoaderUtils.log_debug(str("Checking dependencies - mod_id: ", mod_id, " dependencies: ", deps), LOG_NAME)

# loop through each dependency
for dependency_id in deps:
Expand All @@ -392,7 +343,7 @@ func _check_dependencies(mod_id:String, deps:Array):

# increase importance score by 1
dependency.importance = dependency.importance + 1
dev_log(str("Dependency -> ", dependency_id, " importance -> ", dependency.importance), LOG_NAME)
ModLoaderUtils.log_debug(str("Dependency -> ", dependency_id, " importance -> ", dependency.importance), LOG_NAME)

# check if dependency has dependencies
if(dependency_mod_manifest.dependencies.size() > 0):
Expand All @@ -401,7 +352,7 @@ func _check_dependencies(mod_id:String, deps:Array):

# Handle missing dependencies: Sets `is_loadable` to false and logs an error
func _handle_missing_dependency(mod_id, dependency_id):
mod_log(str("ERROR - missing dependency - mod_id -> ", mod_id, " dependency_id -> ", dependency_id), LOG_NAME)
ModLoaderUtils.log_error(str("Missing dependency - mod_id -> ", mod_id, " dependency_id -> ", dependency_id), LOG_NAME)
# if mod is not present in the missing dependencies array
if(!mod_missing_dependencies.has(mod_id)):
# add it
Expand Down Expand Up @@ -440,15 +391,15 @@ func _compare_importance(a, b):
func _init_mod(mod: ModData):
var mod_main_path = mod.get_required_mod_file_path(ModData.required_mod_files.MOD_MAIN)

dev_log("Loading script from -> %s" % mod_main_path, LOG_NAME)
ModLoaderUtils.log_debug("Loading script from -> %s" % mod_main_path, LOG_NAME)
var mod_main_script = ResourceLoader.load(mod_main_path)
dev_log("Loaded script -> %s" % mod_main_script, LOG_NAME)
ModLoaderUtils.log_debug("Loaded script -> %s" % mod_main_script, LOG_NAME)

var mod_main_instance = mod_main_script.new(self)
# mod_main_instance.name = mod.mod_manifest.extra.godot.id
mod_main_instance.name = mod.manifest.get_mod_id()

dev_log("Adding child -> %s" % mod_main_instance, LOG_NAME)
ModLoaderUtils.log_debug("Adding child -> %s" % mod_main_instance, LOG_NAME)
add_child(mod_main_instance, true)


Expand Down Expand Up @@ -495,19 +446,15 @@ func _get_local_folder_dir(subfolder:String = ""):


func _get_file_name(path, is_lower_case = true, is_no_extension = false):
# mod_log(str("Get file name from path -> ", path), LOG_NAME)
var file_name = path.get_file()

if(is_lower_case):
# mod_log(str("Get file name in lower case"), LOG_NAME)
file_name = file_name.to_lower()

if(is_no_extension):
# mod_log(str("Get file name without extension"), LOG_NAME)
var file_extension = file_name.get_extension()
file_name = file_name.replace(str(".",file_extension), '')

# mod_log(str("return file name -> ", file_name), LOG_NAME)
return file_name


Expand Down Expand Up @@ -577,7 +524,7 @@ func _get_flat_view_dict(p_dir = "res://", p_match = "", p_match_is_regex = fals
func install_script_extension(child_script_path:String):
# Check path to file exists
if !File.new().file_exists(child_script_path):
mod_log("ERROR - The child script path '%s' does not exist" % [child_script_path], LOG_NAME)
ModLoaderUtils.log_error("The child script path '%s' does not exist" % [child_script_path], LOG_NAME)
return

var child_script = ResourceLoader.load(child_script_path)
Expand All @@ -593,7 +540,7 @@ func install_script_extension(child_script_path:String):

var parent_script = child_script.get_base_script()
var parent_script_path = parent_script.resource_path
mod_log("Installing script extension: %s <- %s" % [parent_script_path, child_script_path], LOG_NAME)
ModLoaderUtils.log_info("Installing script extension: %s <- %s" % [parent_script_path, child_script_path], LOG_NAME)
child_script.take_over_path(parent_script_path)


Expand All @@ -603,7 +550,7 @@ func install_script_extension(child_script_path:String):
func add_translation_from_resource(resource_path: String):
var translation_object = load(resource_path)
TranslationServer.add_translation(translation_object)
mod_log(str("Added Translation from Resource -> ", resource_path), LOG_NAME)
ModLoaderUtils.log_info(str("Added Translation from Resource -> ", resource_path), LOG_NAME)


func append_node_in_scene(modified_scene, node_name:String = "", node_parent = null, instance_path:String = "", is_visible:bool = true):
Expand All @@ -628,9 +575,9 @@ func append_node_in_scene(modified_scene, node_name:String = "", node_parent = n
func save_scene(modified_scene, scene_path:String):
var packed_scene = PackedScene.new()
packed_scene.pack(modified_scene)
dev_log(str("packing scene -> ", packed_scene), LOG_NAME)
ModLoaderUtils.log_debug(str("packing scene -> ", packed_scene), LOG_NAME)
packed_scene.take_over_path(scene_path)
dev_log(str("save_scene - taking over path - new path -> ", packed_scene.resource_path), LOG_NAME)
ModLoaderUtils.log_debug(str("save_scene - taking over path - new path -> ", packed_scene.resource_path), LOG_NAME)
_saved_objects.append(packed_scene)


Expand Down Expand Up @@ -688,7 +635,7 @@ func get_mod_config(mod_id:String = "", key:String = "")->Dictionary:

# Log if any errors occured
if error_num != 0:
dev_log(str("Config: ", error_msg), mod_id)
ModLoaderUtils.log_debug(str("Config: ", error_msg), mod_id)

return {
"error": error_num,
Expand Down
Loading