From 7620c3b54e79884249ccb3a64b4257f175b4c587 Mon Sep 17 00:00:00 2001 From: Serkyo Date: Tue, 14 Jul 2026 01:38:58 +0200 Subject: [PATCH] feat(client): connect to server and complete handshake --- crates/client/Cargo.toml | 1 + crates/client/src/main.rs | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index da5ab9c..76f90d6 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -19,3 +19,4 @@ raw-window-handle.workspace = true ash-window.workspace = true serde_json.workspace = true shared = { path = "../shared" } +net = { version = "0.1.0", path = "../net" } diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index e1683aa..7c40862 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -56,6 +56,8 @@ struct App { input: InputState, /// Timestamp of the previous frame, used to derive delta-time. `None` before the first frame. last_frame: Option, + /// Receives the outcome of the background connect and handshake, drained non-blocking from the event loop. `None` before the connection is started and once the outcome has been observed. + handshake_rx: Option, } impl Default for App { @@ -71,6 +73,7 @@ impl Default for App { ), input: InputState::default(), last_frame: None, + handshake_rx: None, } } } @@ -177,6 +180,21 @@ impl ApplicationHandler for App { .expect("Renderer initialized") .update_mesh(&vertices, &indices) .expect("Failed to upload terrain to GPU"); + + // Kick off a background connect + handshake to the local server. + let hello = shared::protocol::ClientHello { + protocol_version: shared::protocol::PROTOCOL_VERSION, + client_build: env!("CARGO_PKG_VERSION").to_owned(), + player_identity: shared::protocol::PlayerIdentity { + display_name: "Player".to_owned(), + }, + installed_packs: Vec::new(), + requested_features: shared::protocol::FeatureFlags(0), + }; + let server_addr = + std::net::SocketAddr::from((std::net::Ipv4Addr::LOCALHOST, net::DEFAULT_PORT)); + info!("Connecting to server at {server_addr}"); + self.handshake_rx = Some(net::connect_in_background(server_addr, hello)); } fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { @@ -200,6 +218,29 @@ impl ApplicationHandler for App { } } WindowEvent::RedrawRequested => { + // Non-blocking check for the handshake outcome. + let mut handshake_done = false; + if let Some(rx) = self.handshake_rx.as_ref() { + match rx.try_recv() { + Ok(Ok(ack)) => { + info!( + protocol_version = ack.protocol_version, + "handshake complete" + ); + handshake_done = true; + } + Ok(Err(reason)) => { + warn!("handshake failed: {reason}"); + handshake_done = true; + } + // Empty: not ready yet. Disconnected: the network thread ended. + Err(_) => {} + } + } + if handshake_done { + self.handshake_rx = None; + } + // Derive delta-time from the previous frame so movement is framerate-independent. The first frame has no predecessor and therefore advances by zero seconds. let now = Instant::now(); let dt = self