use std::error::Error; use futures::stream::{SplitSink, SplitStream}; use futures::StreamExt; use log::{debug, error, info, Level, trace}; use wasm_bindgen::prelude::*; use ws_stream_wasm::{WsMessage, WsMeta, WsStream}; use protocol::State; use protocol::PROTOCOL_VERSION; use protocol::MessageS2C; use protocol::MessageC2S; use futures::SinkExt; #[macro_use] pub mod macros; #[wasm_bindgen] extern { pub fn alert(s: &str); } #[wasm_bindgen] pub fn send_chat(chat: &str) { info!("sending chat: {}", chat); } #[wasm_bindgen] pub async fn rust_init(gateway: &str, username: &str) -> Result<(), JsError> { console_log::init_with_level(Level::Debug).unwrap(); info!("Logger setup successfully"); match main(gateway, username).await { Ok(c) => c, Err(e) => { error!("Error initializing gateway client: {}", e); return Err(JsError::new(&e.to_string())); } }; info!("Gateway client exited"); Ok(()) } pub struct Client { pub state: State, pub tx: SplitSink, pub rx: SplitStream } pub async fn main(gateway: &str, username: &str) -> Result<(), Box> { info!("FAST CONNECT: {}", gateway); let gateway_url = url::Url::parse(gateway)?; trace!("Gateway URL parsed"); let (_ws, ws_stream) = WsMeta::connect(gateway_url, None).await?; trace!("Connected to gateway socket"); let (tx, rx) = ws_stream.split(); let mut client = Client { state: State::Handshake, tx, rx }; trace!("Split stream, handshaking with server"); send!(client.tx, &MessageC2S::Hello { next_state: State::Play, version: PROTOCOL_VERSION, requested_username: username.to_string() }).await?; trace!("Sent handshake start packet"); if let Some(msg) = recv_now!(client.rx)? { let typed_msg: MessageS2C = msg; match typed_msg { MessageS2C::Hello { version, given_username, next_state } => { info!("FAST CONNECT - connected to server protocol {} given username {}, switching to state {:?}", version, given_username, next_state); client.state = next_state; }, MessageS2C::Goodbye { reason } => { error!("server disconnected before finishing handshake: {:?}", reason); return Err(format!("disconnected by server: {:?}", reason).into()); } } } else { error!("Server closed the connection") } Ok(()) }