feat(client): connect to server and complete handshake

This commit is contained in:
Serkyo 2026-07-14 01:38:58 +02:00
parent e941415836
commit 7620c3b54e
2 changed files with 42 additions and 0 deletions

View file

@ -19,3 +19,4 @@ raw-window-handle.workspace = true
ash-window.workspace = true ash-window.workspace = true
serde_json.workspace = true serde_json.workspace = true
shared = { path = "../shared" } shared = { path = "../shared" }
net = { version = "0.1.0", path = "../net" }

View file

@ -56,6 +56,8 @@ struct App {
input: InputState, input: InputState,
/// Timestamp of the previous frame, used to derive delta-time. `None` before the first frame. /// Timestamp of the previous frame, used to derive delta-time. `None` before the first frame.
last_frame: Option<Instant>, last_frame: Option<Instant>,
/// 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<net::ConnectOutcome>,
} }
impl Default for App { impl Default for App {
@ -71,6 +73,7 @@ impl Default for App {
), ),
input: InputState::default(), input: InputState::default(),
last_frame: None, last_frame: None,
handshake_rx: None,
} }
} }
} }
@ -177,6 +180,21 @@ impl ApplicationHandler for App {
.expect("Renderer initialized") .expect("Renderer initialized")
.update_mesh(&vertices, &indices) .update_mesh(&vertices, &indices)
.expect("Failed to upload terrain to GPU"); .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) { fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
@ -200,6 +218,29 @@ impl ApplicationHandler for App {
} }
} }
WindowEvent::RedrawRequested => { 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. // 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 now = Instant::now();
let dt = self let dt = self