~starkingdoms/starkingdoms

296b5c9ee0b1ea5d2c63308dee04f31acafe6a7c — core 2 years ago 896c61d
multiple players support
M client/src/lib.rs => client/src/lib.rs +18 -9
@@ 1,4 1,5 @@
use std::error::Error;
use std::panic;
use std::str::FromStr;

use futures::stream::{SplitSink, SplitStream};


@@ 7,7 8,7 @@ use log::{debug, error, info, Level, trace, warn};
use wasm_bindgen::prelude::*;
use web_sys::console::debug;
use ws_stream_wasm::{WsErr, WsMessage, WsMeta, WsStream};
use starkingdoms_protocol::{ProtocolPlanet, State};
use starkingdoms_protocol::{ProtocolPlanet, ProtocolPlayer, State};
use starkingdoms_protocol::PROTOCOL_VERSION;
use starkingdoms_protocol::MessageS2C;
use starkingdoms_protocol::MessageC2S;


@@ 43,7 44,8 @@ pub struct Client {
    pub client_data: Option<ClientData>,
    pub planets: Vec<ProtocolPlanet>,
    pub x: f64,
    pub y: f64
    pub y: f64,
    pub players: Vec<ProtocolPlayer>
}

#[derive(Debug)]


@@ 53,7 55,8 @@ pub struct ClientData {
    pub rx: SplitStream<WsStream>,
    pub pong_timeout: u64,
    pub textures: TextureLoader,
    pub renderer: WebRenderer
    pub renderer: WebRenderer,
    pub username: String
}

pub const PONG_MAX_TIMEOUT: u64 = 5;


@@ 63,7 66,8 @@ lazy_static! {
        client_data: None,
        planets: vec![],
        x: 0f64,
        y: 0f64
        y: 0f64,
        players: vec![]
    }));
}



@@ 71,7 75,7 @@ pub const MAX_CONNECTION_TRIES: i32 = 10;

#[wasm_bindgen]
pub async fn rust_init(gateway: &str, username: &str, texture_size: &str) -> Result<(), JsValue> {
    console_error_panic_hook::set_once();
    panic::set_hook(Box::new(console_error_panic_hook::hook));

    set_status("Starting logger...");



@@ 139,7 143,8 @@ pub async fn main(gateway: &str, username: &str, backoff: i32, textures: Texture
        rx,
        pong_timeout: (js_sys::Date::now() as u64 / 1000) + 5,
        textures,
        renderer
        renderer,
        username: username.to_string()
    };

    trace!("Split stream, handshaking with server");


@@ 252,9 257,13 @@ pub async fn update_socket() -> Result<(), JsError> {
            MessageS2C::PlanetData { planets } => {
                client.planets = planets;
            },
            MessageS2C::Position { x, y } => {
                client.x = x;
                client.y = y;
            MessageS2C::PlayersUpdate { players } => {
                let me = players.iter().find(|i| i.username == client_data.username);
                if let Some(me) = me {
                    client.x = me.x;
                    client.y = me.y;
                }
                client.players = players;
            }
            _ => {
                warn!("server sent unexpected packet {:?}, ignoring", msg);

M client/src/rendering/renderer.rs => client/src/rendering/renderer.rs +3 -0
@@ 53,6 53,9 @@ impl Renderer for WebRenderer {
            context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, -planet.radius, -planet.radius, planet.radius * 2f64, planet.radius * 2f64).map_err(|e: JsValue| e.as_string().unwrap())?;
            context.restore();
        }



        // do not remove
        // im making this smiley an easter egg soon
        // i just have to go fix the broken build system first

M protocol/src/lib.rs => protocol/src/lib.rs +9 -4
@@ 47,10 47,7 @@ pub enum MessageS2C {
    Pong {},

    PlayersUpdate {
        rotation: Vec<f64>,
        x: Vec<f64>,
        y: Vec<f64>,
        username: Vec<String>,
        players: Vec<ProtocolPlayer>
    },




@@ 60,6 57,14 @@ pub enum MessageS2C {
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ProtocolPlayer {
    pub rotation: f64,
    pub x: f64,
    pub y: f64,
    pub username: String
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum GoodbyeReason {
    UnsupportedProtocol { supported: u32, got: u32 },
    UnexpectedPacket,

M server/src/handler.rs => server/src/handler.rs +2 -5
@@ 33,12 33,9 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
                        from
                    }).await?;
                }
                ClientHandlerMessage::PlayersUpdate { rotation, x, y, usernames } => {
                ClientHandlerMessage::PlayersUpdate { players } => {
                    send!(client_tx, &MessageS2C::PlayersUpdate {
                        rotation,
                        x,
                        y,
                        username: usernames
                        players
                    }).await?;
                }
                ClientHandlerMessage::PlanetData { planets } => {

M server/src/manager.rs => server/src/manager.rs +2 -2
@@ 5,7 5,7 @@ use std::sync::Arc;

use rapier2d_f64::na::{Vector2};
use rapier2d_f64::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet, RigidBodyHandle};
use starkingdoms_protocol::ProtocolPlanet;
use starkingdoms_protocol::{ProtocolPlanet, ProtocolPlayer};
use tokio::sync::mpsc::Sender;
use tokio::sync::RwLock;



@@ 61,6 61,6 @@ impl PhysicsData {
pub enum ClientHandlerMessage {
    Tick,
    ChatMessage { from: String, message: String },
    PlayersUpdate { rotation: Vec<f64>, x: Vec<f64>, y: Vec<f64>, usernames: Vec<String> },
    PlayersUpdate { players: Vec<ProtocolPlayer> },
    PlanetData { planets: Vec<ProtocolPlanet> },
}

M server/src/timer.rs => server/src/timer.rs +29 -19
@@ 3,7 3,7 @@ use std::{time::Duration, sync::Arc};
use log::{error};

use rapier2d_f64::prelude::{PhysicsPipeline, RigidBodyHandle};
use starkingdoms_protocol::{ProtocolPlanet, PlanetType};
use starkingdoms_protocol::{ProtocolPlanet, PlanetType, ProtocolPlayer};
use tokio::{time::sleep, sync::RwLock};
use crate::{manager::{ClientHandlerMessage, ClientManager, PhysicsData}, SCALE};



@@ 14,34 14,44 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData

        physics_data.write().await.tick(&mut pipeline);

        let physics_data = physics_data.read().await;

        let mut protocol_players = vec![];

        for (player_id, player) in mgr.players.read().await.iter() {
            let player_handle = player.handle;
            let player_body = physics_data.rigid_body_set.get(player_handle).unwrap();

            let translation = player_body.translation();
            let rotation = player_body.rotation();

            let username;
            {
                let usernames = mgr.usernames.read().await;
                username = usernames.get(player_id).unwrap().clone();
            }

            protocol_players.push(ProtocolPlayer {
                rotation: rotation.angle(),
                x: translation.x * SCALE,
                y: translation.y * SCALE,
                username,
            });
        }

        for (_addr, client_thread) in mgr.handlers.read().await.iter() {
            match client_thread.tx.send(ClientHandlerMessage::Tick).await {
                Ok(_) => {
                    let player_handles = mgr.players.read().await.values().map(|s| {s.handle}).collect::<Vec<_>>();
                    let data = physics_data.read().await;
                    let mut translations = Vec::new();
                    let mut rotations = Vec::new();
                    for handle in player_handles {
                        let player_body = data.rigid_body_set.get(handle).unwrap();
                        translations.push(player_body.translation());
                        rotations.push(player_body.rotation().angle());
                    }
                    let usernames_raw = mgr.usernames.read().await;
                    let usernames = usernames_raw.values().collect::<Vec<_>>();

                    match client_thread.tx.send(ClientHandlerMessage::PlayersUpdate {
                        rotation: rotations,
                        usernames: usernames.into_iter().map(|s| s.clone()).collect(),
                        x: translations.clone().into_iter().map(|s| { s.x * SCALE}).collect(),
                        y: translations.into_iter().map(|s| { s.y * SCALE}).collect() }).await {
                    match client_thread.tx.send(ClientHandlerMessage::PlayersUpdate {players: protocol_players.clone()}).await {
                        Ok(_) => (),
                        Err(e) => {
                            error!("unable to send position packet: {}", e);
                        }
                    };

                    let world = world_data.read().await;
                    let earth_handle = world.get(0).unwrap();
                    let earth_body = data.rigid_body_set.get(*earth_handle).unwrap();
                    let earth_body = physics_data.rigid_body_set.get(*earth_handle).unwrap();
                    //let earth_collider = data.collider_set.get(earth_body.colliders()[0]).unwrap();
                    let protocol_earth = ProtocolPlanet {
                        planet_type: PlanetType::Earth,