extends SceneTree var failed := 0 func check(ok: bool, label: String) -> void: print("PASS " if ok else "FAIL ", label) if not ok: failed += 1 func _initialize() -> void: call_deferred("run") func run() -> void: create_timer(30).timeout.connect(func(): quit(2)) var game := (load("res://scenes/main.tscn") as PackedScene).instantiate() as Node3D root.add_child(game) await physics_frame for id: String in MapCatalog.IDS: game.select_map(id) await physics_frame await physics_frame var arena: RelayArena = game.arena check(arena.map_id == id, "selected " + id) var capsule := CapsuleShape3D.new() capsule.height = 1.8 capsule.radius = 0.36 for point in arena.spawn_points: var q := PhysicsShapeQueryParameters3D.new() q.shape = capsule q.collision_mask = 1 q.transform.origin = point + Vector3.UP * 0.95 check(arena.get_world_3d().direct_space_state.intersect_shape(q).is_empty(), id + " spawn clearance " + str(point)) var route := arena.navigation.path(point, arena.spawn_points[0]) check(not route.is_empty() and route[-1].distance_to(arena.spawn_points[0]) < 0.7, id + " connected spawn " + str(point)) var path := arena.navigation.path(arena.spawn_points[0], arena.patrol_points[0]) check(not path.is_empty() and path[-1].distance_to(arena.patrol_points[0]) < 1, id + " patrol reachable") game.ui.play_menu() check(game.ui.fields.map.item_count == 2, "PLAY has both maps") game.ui.host_menu() check(game.ui.fields.map.item_count == 2, "HOST has both maps") game.port = 27990 var settings: Dictionary = game.config.duplicate() settings["map"] = "dust2" settings.bots = 7 check(game.host(settings), "host Dust2") check(game.players.size() == 8 and game.config.map == game.arena.map_id, "8 actors on selected map") game.leave() await process_frame game.free() print("MAP SELECTION failures=", failed) quit(0 if failed == 0 else 1)