extends GutTest func test_value_objects_round_trip_and_reject_invalid_data() -> void: var entity_ref := WorldEntityRef.create(&"npc", &"7") var address := SpatialAddress.create(&"jajce", &"village_square", Vector3(2.0, 3.0, 4.0)) assert_not_null(entity_ref) assert_eq( WorldEntityRef.from_dictionary(entity_ref.to_dictionary()).to_dictionary(), entity_ref.to_dictionary() ) assert_not_null(address) assert_eq( SpatialAddress.from_dictionary(address.to_dictionary()).to_dictionary(), address.to_dictionary() ) assert_null(WorldEntityRef.create(&"npc", &"")) assert_null( ( SpatialAddress . from_dictionary( { "schema_version": SpatialAddress.SCHEMA_VERSION, "world_id": "jajce", "location_id": "square", "position": [0.0, 1.0], } ) ) ) func test_record_serialization_is_deterministic_and_defensive() -> void: var actor := WorldEntityRef.create(&"npc", &"7") var resource := WorldEntityRef.create(&"resource", &"berry_patch_a") var participants := { &"source": resource, &"actor": actor, } var payload := { &"zeta": 2, &"alpha": &"food", &"nested": {&"beta": 2, &"alpha": 1}, } var event := WorldEventRecord.create( 42, &"resource_extracted", 12, participants, SpatialAddress.create(&"jajce", &"forest_edge", Vector3(4.0, 0.0, 8.0)), payload ) participants.clear() payload[&"zeta"] = 99 var serialized := event.to_dictionary() var restored := WorldEventRecord.from_dictionary(serialized) assert_not_null(restored) assert_eq(restored.to_dictionary(), serialized) assert_eq(JSON.stringify(restored.to_dictionary()), JSON.stringify(serialized)) assert_eq(restored.get_participant_roles(), [&"actor", &"source"]) assert_eq(restored.get_payload()["zeta"], 2) assert_eq(restored.get_payload()["alpha"], "food") serialized["payload"]["zeta"] = 100 assert_eq(restored.get_payload()["zeta"], 2) func test_store_indexes_id_type_participant_location_and_tick() -> void: var store := WorldEventStore.new() var actor_a := WorldEntityRef.create(&"npc", &"7") var actor_b := WorldEntityRef.create(&"npc", &"8") var pantry := WorldEntityRef.create(&"storage", &"village_pantry") var square := SpatialAddress.create(&"jajce", &"village_square", Vector3.ZERO) var forest := SpatialAddress.create(&"jajce", &"forest_edge", Vector3(12.0, 0.0, 4.0)) var later_event := WorldEventRecord.create( 20, &"storage_deposited", 9, {&"actor": actor_a, &"destination": pantry}, square, {"item_id": "food", "amount": 2.0} ) var earlier_event := WorldEventRecord.create( 7, &"resource_extracted", 4, {&"actor": actor_a}, forest, {"item_id": "food", "amount": 2.0} ) var same_tick_event := WorldEventRecord.create( 9, &"storage_deposited", 9, {&"actor": actor_b, &"source": pantry}, square, {"item_id": "food", "amount": 1.0} ) assert_true(store.append(later_event)) assert_true(store.append(earlier_event)) assert_true(store.append(same_tick_event)) assert_false(store.append(later_event)) assert_same(store.get_by_id(20), store.get_by_id(20)) assert_eq(_event_ids(store.get_all()), [7, 9, 20]) assert_eq(_event_ids(store.get_for_type(&"storage_deposited")), [9, 20]) assert_eq(_event_ids(store.get_for_participant(actor_a)), [7, 20]) assert_eq(_event_ids(store.get_for_participant(pantry)), [9, 20]) assert_eq(_event_ids(store.get_for_location(square)), [9, 20]) assert_eq(_event_ids(store.get_for_tick(9)), [9, 20]) assert_eq(_event_ids(store.get_between_ticks(4, 9)), [7, 9, 20]) assert_true(store.get_for_type(&"unknown").is_empty()) func test_store_round_trip_rebuilds_all_indexes_transactionally() -> void: var original := WorldEventStore.new() var actor := WorldEntityRef.create(&"npc", &"3") var address := SpatialAddress.create(&"jajce", &"pasture", Vector3(1.0, 0.0, 2.0)) assert_true( original.append( WorldEventRecord.create( 5, &"animal_fed", 14, {&"actor": actor}, address, {"amount": 1.0} ) ) ) var serialized := original.to_dictionary() var restored := WorldEventStore.from_dictionary(serialized) assert_not_null(restored) assert_eq(restored.to_dictionary(), serialized) assert_eq(_event_ids(restored.get_for_type(&"animal_fed")), [5]) assert_eq(_event_ids(restored.get_for_participant(actor)), [5]) assert_eq(_event_ids(restored.get_for_location(address)), [5]) assert_eq(_event_ids(restored.get_for_tick(14)), [5]) var invalid_restore := { "schema_version": WorldEventStore.SCHEMA_VERSION, "events": [serialized["events"][0], serialized["events"][0]], } assert_false(restored.restore_from_dictionary(invalid_restore)) assert_eq(restored.to_dictionary(), serialized) func test_economic_event_compatibility_conversion_preserves_contract() -> void: var economic := EconomicEventRecord.create( 12, &"storage_deposited", 30, 4, &"npc_inventory_4", &"village_pantry", &"food", 2.5, Vector3(3.0, 0.0, 7.0) ) economic.data["custom_fact"] = {"reason": "harvest"} var world_event := WorldEventRecord.from_economic_event(economic, &"jajce", &"village_pantry") var round_tripped := world_event.to_economic_event() assert_not_null(world_event) assert_eq(world_event.get_event_id(), 12) assert_eq(world_event.get_participant(&"actor").get_entity_id(), &"4") assert_eq(world_event.get_participant(&"source").get_entity_id(), &"npc_inventory_4") assert_eq(world_event.get_participant(&"destination").get_entity_id(), &"village_pantry") assert_eq(round_tripped.to_dictionary(), economic.to_dictionary()) var store := WorldEventStore.new() assert_not_null(store.append_economic(economic, &"jajce", &"village_pantry")) assert_eq(store.get_by_id(12).to_economic_event().to_dictionary(), economic.to_dictionary()) func _event_ids(events: Array[WorldEventRecord]) -> Array[int]: var ids: Array[int] = [] for event in events: ids.append(event.get_event_id()) return ids