# datapack_creator.gd class_name DatapackCreator extends RefCounted # --- UPDATED CONSTANTS --- const BASE_DATAPACKS_PATH = "user://datapacks/" const CONTENT_SUBDIR = "objects" const METADATA_FILENAME = "config.szpack" # Renamed from METADATA_FILENAME const DATAPACK_RESOURCE_FILENAME = "datapack.tres" # Renamed from DATAPACK_RESOURCE_FILENAME const ASSETS_SUBDIR = "assets" # Renamed from MEDIA_SUBDIR # --- INTERNAL STATE --- var _saved_resources: Dictionary = {} var _pack_base_path: String = "" # --- PUBLIC METHOD --- ## Saves a DatapackModel and all its content resources to the file system. ## 'pack_name' is used to create the final folder structure: user://datapacks/[pack_name]/ func save_datapack(datapack: DatapackModel, pack_name: String) -> bool: var full_pack_name = pack_name.validate_node_name() if full_pack_name.is_empty(): push_error("DatapackCreator: Invalid pack_name provided.") return false _pack_base_path = BASE_DATAPACKS_PATH + full_pack_name + "/" var content_path = _pack_base_path + CONTENT_SUBDIR var assets_path = _pack_base_path + ASSETS_SUBDIR var success_dirs = true success_dirs &= _make_dir_recursive_safe(_pack_base_path) success_dirs &= _make_dir_recursive_safe(content_path) success_dirs &= _make_dir_recursive_safe(assets_path) if not success_dirs: push_error("DatapackCreator: Failed to create necessary directories.") return false _saved_resources.clear() if not _save_content_objects(datapack.content_objects, content_path + "/"): return false var main_resource_path = _pack_base_path + DATAPACK_RESOURCE_FILENAME if not _save_single_resource(datapack, main_resource_path): return false if not _write_metadata_file(datapack, _pack_base_path + METADATA_FILENAME): return false print("Datapack saved successfully to: %s" % _pack_base_path) return true # --- PRIVATE HELPER METHODS --- func _make_dir_recursive_safe(path: String) -> bool: var error = DirAccess.make_dir_recursive_absolute(path) if error != OK and error != ERR_ALREADY_EXISTS: push_error("DirAccess: Failed to create directory: %s (Error: %s)" % [path, error]) return false return true func _save_content_objects(objects: Array, save_path: String) -> bool: var success = true for obj in objects: if not obj is SzObject: push_error("DatapackCreator: Content array contains non-SzObject: %s" % obj) success = false continue # Filename format: [class_name]_[id].tres var filename = "%s_%s.tres" % [obj.get_class().to_lower(), obj.id.to_lower()] var full_path = save_path + filename if not _save_single_resource(obj, full_path): success = false return success func _save_single_resource(resource: Resource, path: String) -> bool: if _saved_resources.has(resource): return true var error = ResourceSaver.save(resource, path, ResourceSaver.FLAG_COMPRESS | ResourceSaver.FLAG_CHANGE_PATH) if error != OK: push_error("DatapackCreator: Failed to save resource at path '%s'. Error: %s" % [path, error]) return false _saved_resources[resource] = path return true func _write_metadata_file(datapack: DatapackModel, path: String) -> bool: var config = ConfigFile.new() var section = "Datapack" config.set_value(section, "guid", datapack.guid.to_string()) config.set_value(section, "name", datapack.name) config.set_value(section, "version", datapack.version) config.set_value(section, "entry_point", DATAPACK_RESOURCE_FILENAME) var error = config.save(path) if error != OK: push_error("DatapackCreator: Failed to save metadata file at path '%s'. Error: %s" % [path, error]) return false return true