Skip to content

Commit 00b711b

Browse files
authored
Merge pull request #63 from Qubus0/move_other_utils
Move other utils
2 parents 8aadd85 + b61787b commit 00b711b

File tree

3 files changed

+123
-145
lines changed

3 files changed

+123
-145
lines changed

addons/mod_loader/mod_data.gd

+6-25
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func load_manifest() -> void:
4343
ModLoaderUtils.log_info("Loading mod_manifest (manifest.json) for -> %s" % dir_name, LOG_NAME)
4444

4545
# Load meta data file
46-
var manifest_path = get_required_mod_file_path(required_mod_files.MANIFEST)
47-
var manifest_dict = _get_json_as_dict(manifest_path) # todo get from utils
46+
var manifest_path := get_required_mod_file_path(required_mod_files.MANIFEST)
47+
var manifest_dict := ModLoaderUtils.get_json_as_dict(manifest_path)
4848

4949
ModLoaderUtils.log_info("%s loaded manifest data -> %s" % [dir_name, manifest_dict], LOG_NAME)
5050

@@ -59,8 +59,8 @@ func load_manifest() -> void:
5959

6060
# Validates if [member dir_name] matches [method ModManifest.get_mod_id]
6161
func is_mod_dir_name_same_as_id() -> bool:
62-
var manifest_id = manifest.get_mod_id()
63-
if dir_name != manifest_id:
62+
var manifest_id := manifest.get_mod_id()
63+
if not dir_name == manifest_id:
6464
ModLoaderUtils.log_fatal('Mod directory name "%s" does not match the data in manifest.json. Expected "%s"' % [ dir_name, manifest_id ], LOG_NAME)
6565
is_loadable = false
6666
return false
@@ -69,10 +69,10 @@ func is_mod_dir_name_same_as_id() -> bool:
6969

7070
# Confirms that all files from [member required_mod_files] exist
7171
func has_required_files() -> bool:
72-
var file_check = File.new()
72+
var file_check := File.new()
7373

7474
for required_file in required_mod_files:
75-
var file_path = get_required_mod_file_path(required_mod_files[required_file])
75+
var file_path := get_required_mod_file_path(required_mod_files[required_file])
7676

7777
if !file_check.file_exists(file_path):
7878
ModLoaderUtils.log_fatal("ERROR - %s is missing a required file: %s" % [dir_name, file_path], LOG_NAME)
@@ -95,25 +95,6 @@ func get_required_mod_file_path(required_file: int) -> String:
9595
return ""
9696

9797

98-
# Parses JSON from a given file path and returns a dictionary.
99-
# Returns an empty dictionary if no file exists (check with size() < 1)
100-
static func _get_json_as_dict(path:String) -> Dictionary: # todo move to utils
101-
var file = File.new()
102-
103-
if !file.file_exists(path):
104-
file.close()
105-
return {}
106-
107-
file.open(path, File.READ)
108-
var content = file.get_as_text()
109-
110-
var parsed := JSON.parse(content)
111-
if parsed.error:
112-
# log error
113-
return {}
114-
return parsed.result
115-
116-
11798
#func _to_string() -> String:
11899
# todo if we want it pretty printed
119100

addons/mod_loader/mod_loader.gd

+9-116
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,20 @@ var _saved_objects = []
8181

8282
func _init():
8383
# if mods are not enabled - don't load mods
84-
if REQUIRE_CMD_LINE && (!_check_cmd_line_arg("--enable-mods")):
84+
if REQUIRE_CMD_LINE and not ModLoaderUtils.is_running_with_command_line_arg("--enable-mods"):
8585
return
8686

8787
# Log game install dir
88-
ModLoaderUtils.log_info(str("game_install_directory: ", _get_local_folder_dir()), LOG_NAME)
88+
ModLoaderUtils.log_info("game_install_directory: %s" % ModLoaderUtils.get_local_folder_dir(), LOG_NAME)
8989

9090
# check if we want to use a different mods path that is provided as a command line argument
91-
var cmd_line_mod_path = _get_cmd_line_arg("--mods-path")
91+
var cmd_line_mod_path := ModLoaderUtils.get_cmd_line_arg_value("--mods-path")
9292
if cmd_line_mod_path != "":
9393
os_mods_path_override = cmd_line_mod_path
9494
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)
9595

9696
# Check for the CLI arg that overrides the configs path
97-
var cmd_line_configs_path = _get_cmd_line_arg("--configs-path")
97+
var cmd_line_configs_path = ModLoaderUtils.get_cmd_line_arg_value("--configs-path")
9898
if cmd_line_configs_path != "":
9999
os_configs_path_override = cmd_line_configs_path
100100
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)
@@ -154,7 +154,7 @@ func _init():
154154
# (UNPACKED_DIR)
155155
func _load_mod_zips():
156156
# Path to the games mod folder
157-
var game_mod_folder_path = _get_local_folder_dir("mods")
157+
var game_mod_folder_path = ModLoaderUtils.get_local_folder_dir("mods")
158158

159159
var dir = Directory.new()
160160
if dir.open(game_mod_folder_path) != OK:
@@ -257,7 +257,7 @@ func _setup_mods():
257257
# Load mod config JSONs from res://configs
258258
func _load_mod_configs():
259259
var found_configs_count = 0
260-
var configs_path = _get_local_folder_dir("configs")
260+
var configs_path = ModLoaderUtils.get_local_folder_dir("configs")
261261

262262
# CLI override, set with `--configs-path="C://path/configs"`
263263
# (similar to os_mods_path_override)
@@ -266,7 +266,7 @@ func _load_mod_configs():
266266

267267
for dir_name in mod_data:
268268
var json_path = configs_path.plus_file(dir_name + ".json")
269-
var mod_config = ModData._get_json_as_dict(json_path)
269+
var mod_config = ModLoaderUtils.get_json_as_dict(json_path)
270270

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

@@ -306,7 +306,7 @@ func _load_mod_configs():
306306
# which depends on the name used in a given mod ZIP (eg "mods-unpacked/Folder-Name")
307307
func _init_mod_data(mod_folder_path):
308308
# The file name should be a valid mod id
309-
var dir_name = _get_file_name(mod_folder_path, false, true)
309+
var dir_name = ModLoaderUtils.get_file_name_from_path(mod_folder_path, false, true)
310310

311311
# Path to the mod in UNPACKED_DIR (eg "res://mods-unpacked/My-Mod")
312312
var local_mod_path = str(UNPACKED_DIR, dir_name)
@@ -320,7 +320,7 @@ func _init_mod_data(mod_folder_path):
320320
# operation if a mod has a large number of files (eg. Brotato's Invasion mod,
321321
# which has ~1,000 files). That's why it's disabled by default
322322
if DEBUG_ENABLE_STORING_FILEPATHS:
323-
mod.file_paths = _get_flat_view_dict(local_mod_path)
323+
mod.file_paths = ModLoaderUtils.get_flat_view_dict(local_mod_path)
324324

325325

326326
# Run dependency checks on a mod, checking any dependencies it lists in its
@@ -403,113 +403,6 @@ func _init_mod(mod: ModData):
403403
add_child(mod_main_instance, true)
404404

405405

406-
# Utils (Mod Loader)
407-
# =============================================================================
408-
409-
# Util functions used in the mod loading process
410-
411-
# Check if the provided command line argument was present when launching the game
412-
func _check_cmd_line_arg(argument) -> bool:
413-
for arg in OS.get_cmdline_args():
414-
if arg == argument:
415-
return true
416-
417-
return false
418-
419-
# Get the command line argument value if present when launching the game
420-
func _get_cmd_line_arg(argument) -> String:
421-
for arg in OS.get_cmdline_args():
422-
if arg.find("=") > -1:
423-
var key_value = arg.split("=")
424-
# True if the checked argument matches a user-specified arg key
425-
# (eg. checking `--mods-path` will match with `--mods-path="C://mods"`
426-
if key_value[0] == argument:
427-
return key_value[1]
428-
429-
return ""
430-
431-
# Get the path to a local folder. Primarily used to get the (packed) mods
432-
# folder, ie "res://mods" or the OS's equivalent, as well as the configs path
433-
func _get_local_folder_dir(subfolder:String = ""):
434-
var game_install_directory = OS.get_executable_path().get_base_dir()
435-
436-
if OS.get_name() == "OSX":
437-
game_install_directory = game_install_directory.get_base_dir().get_base_dir()
438-
439-
# Fix for running the game through the Godot editor (as the EXE path would be
440-
# the editor's own EXE, which won't have any mod ZIPs)
441-
# if OS.is_debug_build():
442-
if OS.has_feature("editor"):
443-
game_install_directory = "res://"
444-
445-
return game_install_directory.plus_file(subfolder)
446-
447-
448-
func _get_file_name(path, is_lower_case = true, is_no_extension = false):
449-
var file_name = path.get_file()
450-
451-
if(is_lower_case):
452-
file_name = file_name.to_lower()
453-
454-
if(is_no_extension):
455-
var file_extension = file_name.get_extension()
456-
file_name = file_name.replace(str(".",file_extension), '')
457-
458-
return file_name
459-
460-
461-
# Get a flat array of all files in the target directory. This was needed in the
462-
# original version of this script, before becoming deprecated. It may still be
463-
# used if DEBUG_ENABLE_STORING_FILEPATHS is true.
464-
# Source: https://gist.github.com/willnationsdev/00d97aa8339138fd7ef0d6bd42748f6e
465-
func _get_flat_view_dict(p_dir = "res://", p_match = "", p_match_is_regex = false):
466-
var regex = null
467-
if p_match_is_regex:
468-
regex = RegEx.new()
469-
regex.compile(p_match)
470-
if not regex.is_valid():
471-
return []
472-
473-
var dirs = [p_dir]
474-
var first = true
475-
var data = []
476-
while not dirs.empty():
477-
var dir = Directory.new()
478-
var dir_name = dirs.back()
479-
dirs.pop_back()
480-
481-
if dir.open(dir_name) == OK:
482-
dir.list_dir_begin()
483-
var file_name = dir.get_next()
484-
while file_name != "":
485-
if not dir_name == "res://":
486-
first = false
487-
# ignore hidden, temporary, or system content
488-
if not file_name.begins_with(".") and not file_name.get_extension() in ["tmp", "import"]:
489-
# If a directory, then add to list of directories to visit
490-
if dir.current_is_dir():
491-
dirs.push_back(dir.get_current_dir() + "/" + file_name)
492-
# If a file, check if we already have a record for the same name
493-
else:
494-
var path = dir.get_current_dir() + ("/" if not first else "") + file_name
495-
# grab all
496-
if not p_match:
497-
data.append(path)
498-
# grab matching strings
499-
elif not p_match_is_regex and file_name.find(p_match, 0) != -1:
500-
data.append(path)
501-
# grab matching regex
502-
else:
503-
var regex_match = regex.search(path)
504-
if regex_match != null:
505-
data.append(path)
506-
# Move on to the next file in this directory
507-
file_name = dir.get_next()
508-
# We've exhausted all files in this directory. Close the iterator.
509-
dir.list_dir_end()
510-
return data
511-
512-
513406
# Helpers
514407
# =============================================================================
515408

addons/mod_loader/mod_loader_utils.gd

+108-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
extends Node
22
class_name ModLoaderUtils
33

4-
const MOD_LOG_PATH = "user://mods.log"
4+
const LOG_NAME := "ModLoader:ModLoaderUtils"
5+
const MOD_LOG_PATH := "user://mods.log"
56

67
enum verbosity_level {
78
ERROR,
@@ -84,7 +85,7 @@ static func _loader_log(message: String, mod_name: String, log_type: String = "i
8485

8586

8687
static func _write_to_log_file(log_entry: String) -> void:
87-
var log_file = File.new()
88+
var log_file := File.new()
8889

8990
if not log_file.file_exists(MOD_LOG_PATH):
9091
log_file.open(MOD_LOG_PATH, File.WRITE)
@@ -127,8 +128,8 @@ static func is_running_with_command_line_arg(argument: String) -> bool:
127128
# Get the command line argument value if present when launching the game
128129
static func get_cmd_line_arg_value(argument: String) -> String:
129130
for arg in OS.get_cmdline_args():
130-
if arg.find("=") > -1:
131-
var key_value = arg.split("=")
131+
if (arg as String).find("=") > -1:
132+
var key_value := (arg as String).split("=")
132133
# True if the checked argument matches a user-specified arg key
133134
# (eg. checking `--mods-path` will match with `--mods-path="C://mods"`
134135
if key_value[0] == argument:
@@ -147,3 +148,106 @@ static func get_date_time_string() -> String:
147148
]
148149

149150

151+
# Get the path to a local folder. Primarily used to get the (packed) mods
152+
# folder, ie "res://mods" or the OS's equivalent, as well as the configs path
153+
static func get_local_folder_dir(subfolder: String = "") -> String:
154+
var game_install_directory := OS.get_executable_path().get_base_dir()
155+
156+
if OS.get_name() == "OSX":
157+
game_install_directory = game_install_directory.get_base_dir().get_base_dir()
158+
159+
# Fix for running the game through the Godot editor (as the EXE path would be
160+
# the editor's own EXE, which won't have any mod ZIPs)
161+
# if OS.is_debug_build():
162+
if OS.has_feature("editor"):
163+
game_install_directory = "res://"
164+
165+
return game_install_directory.plus_file(subfolder)
166+
167+
168+
# Provide a path, get the file name at the end of the path
169+
static func get_file_name_from_path(path: String, make_lower_case := true, remove_extension := false) -> String:
170+
var file_name := path.get_file()
171+
172+
if make_lower_case:
173+
file_name = file_name.to_lower()
174+
175+
if remove_extension:
176+
file_name = file_name.trim_suffix("." + file_name.get_extension())
177+
178+
return file_name
179+
180+
181+
# Parses JSON from a given file path and returns a dictionary.
182+
# Returns an empty dictionary if no file exists (check with size() < 1)
183+
static func get_json_as_dict(path: String) -> Dictionary:
184+
var file := File.new()
185+
186+
if !file.file_exists(path):
187+
file.close()
188+
return {}
189+
190+
file.open(path, File.READ)
191+
var content := file.get_as_text()
192+
193+
var parsed := JSON.parse(content)
194+
if parsed.error:
195+
log_error("Error parsing JSON", LOG_NAME)
196+
return {}
197+
if not parsed.result is Dictionary:
198+
log_error("JSON is not a dictionary", LOG_NAME)
199+
return {}
200+
return parsed.result
201+
202+
203+
# Get a flat array of all files in the target directory. This was needed in the
204+
# original version of this script, before becoming deprecated. It may still be
205+
# used if DEBUG_ENABLE_STORING_FILEPATHS is true.
206+
# Source: https://gist.github.com/willnationsdev/00d97aa8339138fd7ef0d6bd42748f6e
207+
static func get_flat_view_dict(p_dir := "res://", p_match := "", p_match_is_regex := false) -> Array:
208+
var regex: RegEx
209+
if p_match_is_regex:
210+
regex = RegEx.new()
211+
regex.compile(p_match)
212+
if not regex.is_valid():
213+
return []
214+
215+
var dirs := [p_dir]
216+
var first := true
217+
var data := []
218+
while not dirs.empty():
219+
var dir := Directory.new()
220+
var dir_name: String = dirs.back()
221+
dirs.pop_back()
222+
223+
if dir.open(dir_name) == OK:
224+
dir.list_dir_begin()
225+
var file_name := dir.get_next()
226+
while file_name != "":
227+
if not dir_name == "res://":
228+
first = false
229+
# ignore hidden, temporary, or system content
230+
if not file_name.begins_with(".") and not file_name.get_extension() in ["tmp", "import"]:
231+
# If a directory, then add to list of directories to visit
232+
if dir.current_is_dir():
233+
dirs.push_back(dir.get_current_dir().plus_file(file_name))
234+
# If a file, check if we already have a record for the same name
235+
else:
236+
var path := dir.get_current_dir() + ("/" if not first else "") + file_name
237+
# grab all
238+
if not p_match:
239+
data.append(path)
240+
# grab matching strings
241+
elif not p_match_is_regex and file_name.find(p_match, 0) != -1:
242+
data.append(path)
243+
# grab matching regex
244+
else:
245+
var regex_match := regex.search(path)
246+
if regex_match != null:
247+
data.append(path)
248+
# Move on to the next file in this directory
249+
file_name = dir.get_next()
250+
# We've exhausted all files in this directory. Close the iterator.
251+
dir.list_dir_end()
252+
return data
253+

0 commit comments

Comments
 (0)