57 lines
1.5 KiB
GDScript
57 lines
1.5 KiB
GDScript
class_name ConversationSemantic
|
|
extends RefCounted
|
|
|
|
const MAX_ID_LENGTH := 96
|
|
const MAX_TRACE_SIZE := 32
|
|
|
|
|
|
static func is_valid_id(value: Variant) -> bool:
|
|
if value is not String and value is not StringName:
|
|
return false
|
|
var text := String(value)
|
|
if text.is_empty() or text.length() > MAX_ID_LENGTH:
|
|
return false
|
|
for character in text:
|
|
if not _is_safe_id_character(character):
|
|
return false
|
|
return true
|
|
|
|
|
|
static func normalize_id_array(value: Variant, allow_empty: bool = true) -> Variant:
|
|
if value is not Array and value is not PackedStringArray:
|
|
return null
|
|
var normalized: Array[StringName] = []
|
|
var seen: Dictionary = {}
|
|
for item in value:
|
|
if not is_valid_id(item):
|
|
return null
|
|
var semantic_id := StringName(item)
|
|
if seen.has(semantic_id):
|
|
continue
|
|
seen[semantic_id] = true
|
|
normalized.append(semantic_id)
|
|
if not allow_empty and normalized.is_empty():
|
|
return null
|
|
return normalized
|
|
|
|
|
|
static func normalize_trace(value: Variant) -> Variant:
|
|
var normalized: Variant = normalize_id_array(value)
|
|
if normalized == null or normalized.size() > MAX_TRACE_SIZE:
|
|
return null
|
|
return normalized
|
|
|
|
|
|
static func duplicate_entity(entity: WorldEntityRef) -> WorldEntityRef:
|
|
return entity.duplicate_ref() if entity != null else null
|
|
|
|
|
|
static func _is_safe_id_character(character: String) -> bool:
|
|
var code := character.unicode_at(0)
|
|
return (
|
|
(code >= 48 and code <= 57)
|
|
or (code >= 65 and code <= 90)
|
|
or (code >= 97 and code <= 122)
|
|
or character in ["_", "-", ".", ":"]
|
|
)
|