extends SceneTree class FakeRoutineWorld: extends Node func get_animal_routine_sites( species_id: StringName, animal_id: StringName ) -> Array[Dictionary]: return [ { "site_id": &"%s_%s_meadow" % [species_id, animal_id], "position": Vector3(3.0 if species_id == &"goat" else -3.0, 0.0, 2.0), } ] var failures: Array[String] = [] func _initialize() -> void: call_deferred("_run") func _run() -> void: var catalog := AnimalCatalog.create_core() _check(catalog != null and catalog.rebuild().is_empty(), "Core animal content should validate") if catalog == null: _finish() return var definition_ids := catalog.get_definition_ids() _check( definition_ids == [&"domestic_goat", &"domestic_sheep"], "Animal definitions should iterate in deterministic stable-ID order" ) var goat_definition := catalog.get_definition(&"domestic_goat") var sheep_definition := catalog.get_definition(&"domestic_sheep") _check( ( goat_definition != null and sheep_definition != null and goat_definition.species_id == &"goat" and sheep_definition.species_id == &"sheep" ), "Goat and sheep should be distinct data definitions" ) if goat_definition == null or sheep_definition == null: _finish() return _check( ( goat_definition.behavior_id == AnimalDefinition.BEHAVIOR_GRAZER_ROUTINE and sheep_definition.behavior_id == AnimalDefinition.BEHAVIOR_GRAZER_ROUTINE and goat_definition.presentation_scene_path == sheep_definition.presentation_scene_path ), "Both animals should reuse one grazer behavior and presentation contract" ) _check( ( goat_definition.supports_action(&"feed_animal") and sheep_definition.supports_action(&"feed_animal") ), "Both data definitions should advertise the existing care action" ) var generic_scene := load(goat_definition.presentation_scene_path) as PackedScene var generic := generic_scene.instantiate() as AnimalNode _check( ( generic != null and generic.animal_id.is_empty() and generic.animal_definition_id.is_empty() and generic.species_id.is_empty() and generic.display_name == "Animal" and (generic.get_node("DebugLabel") as Label3D).text == "Animal" ), "The reusable grazer scene should contain no Dunja-specific identity" ) if generic != null: generic.free() var factory := AnimalFactory.new(catalog) var goat := ( factory . create_presentation( &"domestic_goat", &"test_goat", "Dunja Test", { "initial_hunger": 10.0, "initial_routine_site_id": &"goat_barn", "initial_next_routine_tick": 0, "debug_label_enabled": false, } ) ) var sheep := ( factory . create_presentation( &"domestic_sheep", &"test_sheep", "Mila Test", { "initial_hunger": 10.0, "initial_routine_site_id": &"sheep_fold", "initial_next_routine_tick": 0, "debug_label_enabled": false, } ) ) _check(goat != null and sheep != null, "The shared factory should create both definitions") if goat == null or sheep == null: if goat != null: goat.free() if sheep != null: sheep.free() _finish() return root.add_child(goat) root.add_child(sheep) _check( ( goat.get_script() == sheep.get_script() and goat.get_node("Visual").get_script() == sheep.get_node("Visual").get_script() ), "A second animal should add no movement or visual-controller system" ) _check( ( goat.get_node("Visual/HeadRoot/HornLeft").visible and not sheep.get_node("Visual/HeadRoot/HornLeft").visible and not sheep.get_node("Visual/HeadRoot/Beard").visible ), "Definition data should configure bounded presentation differences" ) var routine_world := FakeRoutineWorld.new() root.add_child(routine_world) var care := AnimalCareSystem.new() care.configure(null, routine_world) _check(care.configure_animal_catalog(catalog), "Animal care should accept the isolated catalog") var goat_registered := care.register_node(goat) var sheep_registered := care.register_node(sheep) _check( goat_registered and sheep_registered, "Existing AnimalCareSystem should bind both shared-contract nodes" ) var goat_state := care.get_state(&"test_goat") var sheep_state := care.get_state(&"test_sheep") _check( ( goat_state != null and sheep_state != null and goat_state.get_animal_definition_id() == &"domestic_goat" and sheep_state.get_animal_definition_id() == &"domestic_sheep" and goat_state.get_script() == sheep_state.get_script() ), "Authoritative records should retain stable animal definition IDs" ) if goat_state != null and sheep_state != null: var restored_sheep := AnimalStateRecord.from_dictionary(sheep_state.to_dictionary()) _check( ( restored_sheep != null and restored_sheep.get_animal_definition_id() == &"domestic_sheep" and restored_sheep.get_species_id() == &"sheep" ), "The second animal should round-trip through the existing animal record system" ) var started: Array[StringName] = [] care.routine_started.connect( func(animal_id: StringName, _site_id: StringName, _position: Vector3) -> void: started.append(animal_id) ) care.advance(0) started.sort_custom( func(left: StringName, right: StringName) -> bool: return String(left) < String(right) ) _check( ( started == [&"test_goat", &"test_sheep"] and goat_state.has_active_travel_target() and sheep_state.has_active_travel_target() ), "Goat and sheep should execute the same deterministic routine scheduler" ) _test_nested_record_migration(goat_state) goat.free() sheep.free() routine_world.free() _finish() func _test_nested_record_migration(goat_state: AnimalStateRecord) -> void: var previous_record := goat_state.to_dictionary() previous_record["schema_version"] = AnimalStateRecord.ROUTINE_SCHEMA_VERSION previous_record.erase("animal_definition_id") var migrated := AnimalStateRecord.from_dictionary(previous_record) _check( ( migrated != null and migrated.get_animal_definition_id() == &"domestic_goat" and migrated.to_dictionary()["schema_version"] == AnimalStateRecord.SCHEMA_VERSION ), "Nested v2 animal records should migrate to stable goat definition identity" ) var mismatched := goat_state.to_dictionary() mismatched["animal_definition_id"] = "domestic_sheep" var mismatched_record := AnimalStateRecord.from_dictionary(mismatched) _check( ( mismatched_record != null and not AnimalCatalog.create_core().matches_identity( mismatched_record.get_animal_definition_id(), mismatched_record.get_species_id() ) ), "Data-only restore should remain extensible while the catalog detects identity mismatches" ) func _check(condition: bool, message: String) -> void: if not condition: failures.append(message) func _finish() -> void: if failures.is_empty(): print("[TEST] Shared animal definition contract passed") quit(0) return for failure in failures: push_error("[TEST] " + failure) quit(1)