class_name ContentDB extends RefCounted ## Loads authored world content (/content) and cross-checks origin references. ## Mirrors api/app/content.py so client and api resolve ids identically. This is ## content integrity, distinct from JSON-schema validation. var locations: Dictionary = {} var npcs: Dictionary = {} var quests: Dictionary = {} var items: Dictionary = {} static func default_content_root() -> String: return ProjectSettings.globalize_path("res://").path_join("../content").simplify_path() static func origin_path(id: String) -> String: return default_content_root().path_join("origins").path_join("%s.json" % id) static func load_json(abs_path: String) -> Variant: var text := FileAccess.get_file_as_string(abs_path) return JSON.parse_string(text) func load_from(content_root: String) -> void: var world := content_root.path_join("world") locations = _load_dir(world.path_join("locations")) npcs = _load_dir(world.path_join("npcs")) quests = _load_dir(world.path_join("quests")) items = _load_dir(world.path_join("items")) func _load_dir(dir_path: String) -> Dictionary: var out: Dictionary = {} var dir := DirAccess.open(dir_path) if dir == null: push_error("content dir not found: %s" % dir_path) return out for file in dir.get_files(): if not file.ends_with(".json"): continue var data: Variant = load_json(dir_path.path_join(file)) if typeof(data) != TYPE_DICTIONARY or not data.has("id"): push_error("bad content file: %s" % file) continue out[data["id"]] = data return out func location(id: String) -> Dictionary: return locations.get(id, {}) func npc(id: String) -> Dictionary: return npcs.get(id, {}) func quest(id: String) -> Dictionary: return quests.get(id, {}) func item(id: String) -> Dictionary: return items.get(id, {}) func has_location(id: String) -> bool: return locations.has(id) func has_npc(id: String) -> bool: return npcs.has(id) func has_quest(id: String) -> bool: return quests.has(id) func has_item(id: String) -> bool: return items.has(id) func companions() -> Array: var out: Array = [] for id in npcs: if npcs[id].get("role", "") == "companion": out.append(npcs[id]) return out func unresolved_refs(origin: Dictionary) -> Array: var missing: Array = [] var loc: String = origin.get("start_location_id", "") if not has_location(loc): missing.append("location:%s" % loc) var q: Variant = origin.get("start_quest_id", null) if q != null and not has_quest(q): missing.append("quest:%s" % q) for grant in origin.get("inventory_grants", []): if not has_item(grant.get("item_id", "")): missing.append("item:%s" % grant.get("item_id", "")) for npc_id in origin.get("disposition_overrides", {}): if not has_npc(npc_id): missing.append("npc:%s" % npc_id) return missing