~starkingdoms/starkingdoms

ref: dda1b9e50e823af10d1d19ce27bf8a5296c84b9e starkingdoms/client/src/lib.rs -rw-r--r-- 2.5 KiB
dda1b9e5 — core hell is over? 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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<WsStream, WsMessage>,
    pub rx: SplitStream<WsStream>
}

pub async fn main(gateway: &str, username: &str) -> Result<(), Box<dyn Error>> {
    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(())
}