Files
gamedev-the-steward/simulation/state/ConversationActStateRecord.gd
T
2026-08-12 21:15:58 +02:00

112 lines
2.6 KiB
GDScript

class_name ConversationActStateRecord
extends RefCounted
const SCHEMA_VERSION := 1
const MAX_TOPICS := 8
var data: Dictionary
func _init(record_data: Dictionary = {}) -> void:
data = record_data.duplicate(true)
static func create(
act_id: int,
tick: int,
speaker: WorldEntityRef,
listener: WorldEntityRef,
intent_id: StringName,
topic_ids: Array[StringName] = []
) -> ConversationActStateRecord:
if (
act_id < 0
or tick < 0
or speaker == null
or listener == null
or not speaker.is_valid()
or not listener.is_valid()
or speaker.equals(listener)
or not ConversationIntentIds.is_supported(intent_id)
or topic_ids.size() > MAX_TOPICS
):
return null
var normalized_topics: Array[String] = []
var seen: Dictionary = {}
for topic_id in topic_ids:
if topic_id.is_empty() or seen.has(topic_id):
return null
seen[topic_id] = true
normalized_topics.append(String(topic_id))
return (
ConversationActStateRecord
. new(
{
"schema_version": SCHEMA_VERSION,
"act_id": act_id,
"tick": tick,
"speaker": speaker.to_dictionary(),
"listener": listener.to_dictionary(),
"intent_id": String(intent_id),
"topic_ids": normalized_topics,
}
)
)
static func from_dictionary(record_data: Dictionary) -> ConversationActStateRecord:
if (
int(record_data.get("schema_version", -1)) != SCHEMA_VERSION
or not record_data.has_all(
["act_id", "tick", "speaker", "listener", "intent_id", "topic_ids"]
)
or not record_data["speaker"] is Dictionary
or not record_data["listener"] is Dictionary
or not record_data["topic_ids"] is Array
):
return null
var topics: Array[StringName] = []
for topic in record_data["topic_ids"]:
if not topic is String and not topic is StringName:
return null
topics.append(StringName(topic))
return create(
int(record_data["act_id"]),
int(record_data["tick"]),
WorldEntityRef.from_dictionary(record_data["speaker"]),
WorldEntityRef.from_dictionary(record_data["listener"]),
StringName(record_data["intent_id"]),
topics
)
func get_act_id() -> int:
return int(data["act_id"])
func get_tick() -> int:
return int(data["tick"])
func get_speaker() -> WorldEntityRef:
return WorldEntityRef.from_dictionary(data["speaker"])
func get_listener() -> WorldEntityRef:
return WorldEntityRef.from_dictionary(data["listener"])
func get_intent_id() -> StringName:
return StringName(data["intent_id"])
func get_topic_ids() -> Array[StringName]:
var result: Array[StringName] = []
for topic in data["topic_ids"]:
result.append(StringName(topic))
return result
func to_dictionary() -> Dictionary:
return data.duplicate(true)