From 267d4151739dfcaf8d2311fdd6ba1ab5382ab98d Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Fri, 13 Feb 2026 01:19:29 +0100 Subject: [PATCH] feat(simulation): implement content loader Phase 2 (#408) Extend content loader to read and instantiate real YAML content into ECS entities. 2-phase spawn pipeline: Phase 1 creates entities with core components (Want, Tolerance, Contentment, Personality, Tells, Skills), Phase 2 resolves cross-references (Relationships, Secrets, Information via KnowledgeGraph, DailyRoutine). Loads enums, entity attributes, pools, templates, triangles, and NPC profiles. Handles stub files gracefully. 7 integration tests against real content files plus edge case tests for invalid data. Co-Authored-By: Claude Opus 4.6 --- server/Cargo.lock | 32 + server/Cargo.toml | 1 + server/src/content/loader.rs | 619 ++++++++++++++++++ server/src/content/mod.rs | 85 +++ server/src/content/spawn.rs | 1041 +++++++++++++++++++++++++++++++ server/src/content/types.rs | 555 ++++++++++++++++ server/src/lib.rs | 1 + server/src/npc/mod.rs | 1 + server/tests/content_loading.rs | 405 ++++++++++++ 9 files changed, 2740 insertions(+) create mode 100644 server/src/content/loader.rs create mode 100644 server/src/content/mod.rs create mode 100644 server/src/content/spawn.rs create mode 100644 server/src/content/types.rs create mode 100644 server/tests/content_loading.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index f397f2e21..13d7040f3 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -616,6 +616,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + [[package]] name = "js-sys" version = "0.3.85" @@ -902,6 +908,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "semver" version = "1.0.27" @@ -938,6 +950,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "settled-reach-server" version = "0.1.0" @@ -950,6 +975,7 @@ dependencies = [ "rand_chacha", "rmp-serde", "serde", + "serde_yaml", "thiserror", "tracing", "tracing-subscriber", @@ -1164,6 +1190,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "uuid" version = "1.20.0" diff --git a/server/Cargo.toml b/server/Cargo.toml index 61e535a49..57af583e8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" bevy_ecs = "0.18" bevy_app = "0.18" serde = { version = "1", features = ["derive"] } +serde_yaml = "0.9" rmp-serde = "1" bincode = "1" rand = "0.9" diff --git a/server/src/content/loader.rs b/server/src/content/loader.rs new file mode 100644 index 000000000..868d0e9cc --- /dev/null +++ b/server/src/content/loader.rs @@ -0,0 +1,619 @@ +//! Content discovery and deserialization. +//! +//! Reads content.yaml, discovers campaigns and districts via directory +//! structure, deserializes YAML files into intermediate content types. +//! Comment-only YAML files (stubs) are skipped gracefully. + +use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; + +use crate::content::types::*; + +/// All content loaded from disk, organized by district. +/// Inserted as a bevy Resource after loading completes. +#[derive(Debug, Default)] +pub struct ContentStore { + pub manifest: Option, + pub districts: BTreeMap, +} + +/// Content for a single district. +#[derive(Debug, Default)] +pub struct DistrictContent { + pub meta: Option, + pub district_path: PathBuf, + pub pools: Vec, + pub templates: Vec