feat: integrate jajce world into runtime
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
func _run() -> void:
|
||||
var main_scene: Node = load("res://main.tscn").instantiate()
|
||||
root.add_child(main_scene)
|
||||
await process_frame
|
||||
await physics_frame
|
||||
|
||||
var simulation_manager: Node = main_scene.get_node("SimulationManager")
|
||||
simulation_manager.set_process(false)
|
||||
|
||||
_check(simulation_manager.npcs.size() == 3, "Baseline should create three NPCs")
|
||||
_check(
|
||||
main_scene.has_node("JajceWorld/TerrainRoot/Terrain3D"),
|
||||
"Playable runtime should instance the Jajce Terrain3D world"
|
||||
)
|
||||
var terrain: Terrain3D = main_scene.get_node(
|
||||
"JajceWorld/TerrainRoot/Terrain3D"
|
||||
)
|
||||
_check(
|
||||
terrain.get_camera() == main_scene.get_node("CameraRig/Camera3D"),
|
||||
"Runtime Terrain3D should bind to the gameplay camera"
|
||||
)
|
||||
_check(
|
||||
not main_scene.has_node("World")
|
||||
and not main_scene.has_node("ResourceNodes")
|
||||
and not main_scene.has_node("ActivityMarkers"),
|
||||
"Runtime should not retain duplicate flat-world objects"
|
||||
)
|
||||
var resource_root := main_scene.get_node(
|
||||
"JajceWorld/WorldObjects/ResourceNodes"
|
||||
)
|
||||
_check(
|
||||
resource_root.get_child_count() == 4,
|
||||
"Runtime should contain four Jajce ResourceNodes"
|
||||
)
|
||||
_check(
|
||||
simulation_manager.resource_states.size() == 4,
|
||||
"Simulation authority should bind all four Jajce resources"
|
||||
)
|
||||
|
||||
var navigation_map: RID = main_scene.get_world_3d().navigation_map
|
||||
await _wait_for_navigation_map(navigation_map)
|
||||
NavigationServer3D.map_force_update(navigation_map)
|
||||
|
||||
var fixed_origins := [
|
||||
Vector3(-6.0, 0.0, -4.0),
|
||||
Vector3(0.0, 0.0, 0.0),
|
||||
Vector3(6.0, 0.0, 4.0)
|
||||
]
|
||||
var destinations: Array[Vector3] = []
|
||||
for marker_path in [
|
||||
"JajceWorld/LegacyActivityMarkers/PantryMarker",
|
||||
"JajceWorld/LegacyActivityMarkers/GuardZone",
|
||||
"JajceWorld/LegacyActivityMarkers/StudyZone",
|
||||
"JajceWorld/LegacyActivityMarkers/RestZone"
|
||||
]:
|
||||
destinations.append(main_scene.get_node(marker_path).global_position)
|
||||
|
||||
for resource in resource_root.get_children():
|
||||
destinations.append((resource as ResourceNode).interaction_point.global_position)
|
||||
|
||||
for origin in fixed_origins:
|
||||
for destination in destinations:
|
||||
var path := NavigationServer3D.map_get_path(
|
||||
navigation_map,
|
||||
origin,
|
||||
destination,
|
||||
true
|
||||
)
|
||||
_check(
|
||||
not path.is_empty(),
|
||||
"Navigation path should exist from %s to %s" % [origin, destination]
|
||||
)
|
||||
|
||||
var village := SimVillage.new()
|
||||
var worker := SimNPC.new(
|
||||
100,
|
||||
"BaselineWorker",
|
||||
SimulationIds.PROFESSION_SCHOLAR,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
worker.set_task(SimulationIds.ACTION_STUDY, 2.0)
|
||||
worker.start_working()
|
||||
var executor := ActionExecutionSystem.new()
|
||||
executor.advance_npc(worker, village)
|
||||
executor.advance_npc(worker, village)
|
||||
_check(worker.task_complete, "A two-tick working task should complete")
|
||||
|
||||
var starving := SimNPC.new(
|
||||
101,
|
||||
"BaselineStarving",
|
||||
SimulationIds.PROFESSION_WANDERER,
|
||||
5.0,
|
||||
5.0
|
||||
)
|
||||
starving.hunger = 100.0
|
||||
starving.starvation_death_threshold = 1
|
||||
executor.advance_npc(starving, village)
|
||||
_check(starving.is_dead, "Starvation threshold should still kill an NPC")
|
||||
|
||||
if failures.is_empty():
|
||||
print("[TEST] Jajce runtime passed: 3 NPCs, 4 resources, 24 navigation routes")
|
||||
quit(0)
|
||||
return
|
||||
|
||||
for failure in failures:
|
||||
push_error("[TEST] " + failure)
|
||||
quit(1)
|
||||
|
||||
func _wait_for_navigation_map(navigation_map: RID) -> void:
|
||||
for attempt in 30:
|
||||
if (
|
||||
NavigationServer3D.map_get_iteration_id(navigation_map) > 0
|
||||
and not NavigationServer3D.map_get_regions(navigation_map).is_empty()
|
||||
):
|
||||
await physics_frame
|
||||
return
|
||||
await physics_frame
|
||||
_check(false, "Navigation map did not synchronize within 30 physics frames")
|
||||
|
||||
func _check(condition: bool, message: String) -> void:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
Reference in New Issue
Block a user