extends SceneTree const MainScene: PackedScene = preload("res://main/main.tscn") const TEST_PORT: int = 18196 func _initialize() -> void: call_deferred("_run") func _run() -> void: var arguments := OS.get_cmdline_user_args() if arguments.has("host"): await _run_host() return if arguments.has("client"): await _run_client() return push_error("Friend multiplayer validation needs host or client mode.") quit(1) func _run_host() -> void: var main := await _create_initialized_main() var session := main.get_node("%NetworkSession") as NetworkSession var save_manager := main.get("_save_manager") as PlayerSaveManager assert(bool(main.call( "_apply_world", WorldLayout.STARTER_ISLAND, 1, true ))) assert(session.set_host_world(WorldLayout.STARTER_ISLAND, 1)) assert(session.start_private_host(TEST_PORT)) assert(save_manager.initialize_new_game()) main.call("_enter_gameplay") for _frame: int in 4: await physics_frame assert(session.set_host_open(true)) var remote_peer_id := await _wait_for_remote_peer(session) assert(remote_peer_id > 1) assert(session.peer_supports_capability( remote_peer_id, NetworkProtocol.FRIENDS_CAPABILITY )) var remote_record := session.get_peer_record(remote_peer_id) assert(remote_record != null) var game_ui := main.get_node("%GameUI") as GameUI var prompt_deadline := Time.get_ticks_msec() + 8000 while ( Time.get_ticks_msec() < prompt_deadline and not game_ui.is_social_prompt_open() ): await process_frame assert(game_ui.is_social_prompt_open()) await create_timer(0.15).timeout game_ui.call("_accept_social_prompt") var relationships := main.get_node( "%PlayerRelationshipStore" ) as PlayerRelationshipStore var accepted_deadline := Time.get_ticks_msec() + 8000 while ( Time.get_ticks_msec() < accepted_deadline and not relationships.is_friend(remote_record.identity_fingerprint) ): await process_frame assert(relationships.is_friend(remote_record.identity_fingerprint)) var friend := relationships.get_friend_record( remote_record.identity_fingerprint ) assert(not str(friend.get("remote_presence_channel", "")).is_empty()) assert(not str(friend.get("remote_invite_token", "")).is_empty()) var disconnect_deadline := Time.get_ticks_msec() + 8000 while ( Time.get_ticks_msec() < disconnect_deadline and session.is_authenticated_peer(remote_peer_id) ): await process_frame assert(not session.is_authenticated_peer(remote_peer_id)) print("Friend multiplayer host validation: PASS") await _cleanup(main, session) func _run_client() -> void: var main := await _create_initialized_main() main.call( "_on_title_join_game_requested", "127.0.0.1:%d" % TEST_PORT, ) var session := main.get_node("%NetworkSession") as NetworkSession var join_deadline := Time.get_ticks_msec() + 20000 while Time.get_ticks_msec() < join_deadline: await process_frame if session.state == NetworkSession.State.VERIFYING_SERVER_IDENTITY: main.call("_confirm_server_trust") if session.is_joined_client() and bool(main.get("_gameplay_started")): break assert(session.is_joined_client()) assert(session.supports_server_capability( NetworkProtocol.FRIENDS_CAPABILITY )) var host_record := session.get_peer_record(1) assert(host_record != null) var service := main.get_node( "%NetworkPlayerListService" ) as NetworkPlayerListService assert(service.send_friend_request( 1, host_record.identity_fingerprint, host_record.display_name, )) var relationships := main.get_node( "%PlayerRelationshipStore" ) as PlayerRelationshipStore var accepted_deadline := Time.get_ticks_msec() + 8000 while ( Time.get_ticks_msec() < accepted_deadline and not relationships.is_friend(host_record.identity_fingerprint) ): await process_frame assert(relationships.is_friend(host_record.identity_fingerprint)) var friend := relationships.get_friend_record( host_record.identity_fingerprint ) assert(not str(friend.get("remote_presence_channel", "")).is_empty()) assert(not str(friend.get("remote_invite_token", "")).is_empty()) print("Friend multiplayer client validation: PASS") await _cleanup(main, session) func _create_initialized_main() -> Node: root.size = Vector2i(1280, 720) var main := MainScene.instantiate() root.add_child(main) for _frame: int in 4: await process_frame if not bool(main.get("_application_initialized")): main.call("_activate_selected_data_path", "", true) for _frame: int in 8: await process_frame assert(bool(main.get("_application_initialized"))) return main func _wait_for_remote_peer(session: NetworkSession) -> int: var deadline := Time.get_ticks_msec() + 20000 while Time.get_ticks_msec() < deadline: await process_frame for peer_id: int in session.get_authenticated_peer_ids(): if peer_id != session.get_local_peer_id(): return peer_id return 0 func _cleanup(main: Node, session: NetworkSession) -> void: session.disconnect_session("") main.queue_free() for _frame: int in 4: await process_frame await create_timer(0.1).timeout quit()