|
| 1 | +extends Resource |
| 2 | +class_name ModData |
| 3 | + |
| 4 | +# Stores and validates all Data required to load a mod successfully |
| 5 | +# If some of the data is invalid, [member is_loadable] will be false |
| 6 | + |
| 7 | +const LOG_NAME := "ModLoader:ModData" |
| 8 | + |
| 9 | +# These 2 files are always required by mods. |
| 10 | +# [i]mod_main.gd[/i] = The main init file for the mod |
| 11 | +# [i]manifest.json[/i] = Meta data for the mod, including its dependencies |
| 12 | +enum required_mod_files { |
| 13 | + MOD_MAIN, |
| 14 | + MANIFEST, |
| 15 | +} |
| 16 | + |
| 17 | +# Directory of the mod. Has to be identical to [method ModManifest.get_mod_id] |
| 18 | +var dir_name := "" |
| 19 | +# Path to the Mod's Directory |
| 20 | +var dir_path := "" |
| 21 | +# False if any data is invalid |
| 22 | +var is_loadable := true |
| 23 | +# Is increased for every mod depending on this mod. Highest importance is loaded first |
| 24 | +var importance := 0 |
| 25 | +# Contents of the manifest |
| 26 | +var manifest: ModManifest |
| 27 | +# Updated in _load_mod_configs |
| 28 | +var config := {} |
| 29 | + |
| 30 | +# only set if DEBUG_ENABLE_STORING_FILEPATHS is enabled |
| 31 | +var file_paths := [] |
| 32 | + |
| 33 | + |
| 34 | +func _init(_dir_path: String) -> void: |
| 35 | + dir_path = _dir_path |
| 36 | + |
| 37 | + |
| 38 | +# Load meta data from a mod's manifest.json file |
| 39 | +func load_manifest() -> void: |
| 40 | + if not has_required_files(): |
| 41 | + return |
| 42 | + |
| 43 | +# ModLoader.mod_log("Loading mod_manifest (manifest.json) for -> %s" % dir_name, LOG_NAME) |
| 44 | + |
| 45 | + # 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 |
| 48 | + |
| 49 | +# ModLoader.mod_log("%s loaded manifest data -> %s" % [dir_name, manifest_dict], LOG_NAME) |
| 50 | + |
| 51 | + var mod_manifest := ModManifest.new(manifest_dict) |
| 52 | + |
| 53 | + if not mod_manifest: |
| 54 | + is_loadable = false |
| 55 | + return |
| 56 | + |
| 57 | + manifest = mod_manifest |
| 58 | + |
| 59 | + |
| 60 | +# Validates if [member dir_name] matches [method ModManifest.get_mod_id] |
| 61 | +func is_mod_dir_name_same_as_id() -> bool: |
| 62 | + var manifest_id = manifest.get_mod_id() |
| 63 | + if dir_name != manifest_id: |
| 64 | +# ModLoader.mod_log('ERROR - Mod directory name "%s" does not match the data in manifest.json. Expected "%s"' % [ dir_name, manifest_id ], LOG_NAME) |
| 65 | + is_loadable = false |
| 66 | + return false |
| 67 | + return true |
| 68 | + |
| 69 | + |
| 70 | +# Confirms that all files from [member required_mod_files] exist |
| 71 | +func has_required_files() -> bool: |
| 72 | + var file_check = File.new() |
| 73 | + |
| 74 | + for required_file in required_mod_files: |
| 75 | + var file_path = get_required_mod_file_path(required_mod_files[required_file]) |
| 76 | + |
| 77 | + if !file_check.file_exists(file_path): |
| 78 | +# ModLoader.mod_log("ERROR - %s is missing a required file: %s" % [dir_name, file_path], LOG_NAME) |
| 79 | + is_loadable = false |
| 80 | + return is_loadable |
| 81 | + |
| 82 | + |
| 83 | +# Validates if manifest is set |
| 84 | +func has_manifest() -> bool: |
| 85 | + return not manifest == null |
| 86 | + |
| 87 | + |
| 88 | +# Converts enum indices [member required_mod_files] into their respective file paths |
| 89 | +func get_required_mod_file_path(required_file: int) -> String: |
| 90 | + match required_file: |
| 91 | + required_mod_files.MOD_MAIN: |
| 92 | + return dir_path.plus_file("mod_main.gd") |
| 93 | + required_mod_files.MANIFEST: |
| 94 | + return dir_path.plus_file("manifest.json") |
| 95 | + return "" |
| 96 | + |
| 97 | + |
| 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 | + |
| 117 | +#func _to_string() -> String: |
| 118 | + # todo if we want it pretty printed |
| 119 | + |
| 120 | + |
0 commit comments