class_name ConversationTemplateCatalog extends Resource @export var catalog_id: StringName @export var line_templates: Dictionary = {} @export var option_templates: Dictionary = {} func validate(intent_ids: Array[StringName] = ConversationIntentIds.ALL) -> Array[String]: var errors: Array[String] = [] if catalog_id.is_empty(): errors.append("catalog_id is empty") _validate_templates(line_templates, "line", intent_ids, errors) _validate_templates(option_templates, "option", intent_ids, errors) errors.sort() return errors func get_line_templates(intent_id: StringName) -> Array[String]: return _get_templates(line_templates, intent_id) func get_option_templates(intent_id: StringName) -> Array[String]: return _get_templates(option_templates, intent_id) func get_line_template_ids() -> Array[StringName]: return _template_ids(line_templates) func get_option_template_ids() -> Array[StringName]: return _template_ids(option_templates) func _get_templates(source: Dictionary, intent_id: StringName) -> Array[String]: var result: Array[String] = [] var values: Variant = source.get(String(intent_id), []) if values is Array or values is PackedStringArray: for value in values: if value is String: result.append(value) return result func _validate_templates( source: Dictionary, kind: String, intent_ids: Array[StringName], errors: Array[String] ) -> void: var allowed_ids := {} for intent_id in intent_ids: allowed_ids[intent_id] = true for raw_intent_id in source: if not raw_intent_id is String and not raw_intent_id is StringName: errors.append("Non-string %s template intent ID" % kind) continue var source_intent_id := StringName(raw_intent_id) if not allowed_ids.has(source_intent_id): errors.append("Unknown %s template intent '%s'" % [kind, source_intent_id]) var raw_templates: Variant = source[raw_intent_id] if not raw_templates is Array and not raw_templates is PackedStringArray: errors.append("Invalid %s templates for '%s'" % [kind, source_intent_id]) continue for raw_template in raw_templates: if not raw_template is String: errors.append("Non-string %s template for '%s'" % [kind, source_intent_id]) for intent_id in intent_ids: var templates := _get_templates(source, intent_id) if templates.is_empty(): errors.append("Missing %s templates for '%s'" % [kind, intent_id]) continue for template in templates: if template.strip_edges().is_empty(): errors.append("Empty %s template for '%s'" % [kind, intent_id]) func _template_ids(source: Dictionary) -> Array[StringName]: var result: Array[StringName] = [] for raw_id in source: if raw_id is String or raw_id is StringName: result.append(StringName(raw_id)) result.sort_custom( func(left: StringName, right: StringName) -> bool: return String(left) < String(right) ) return result