~starkingdoms/starkingdoms

042d48c0414586735443cef771cb1f227fa16461 — ghostlyzsh 2 years ago 71ce7ed
yay broken, player initialization
M Cargo.lock => Cargo.lock +1 -0
@@ 1371,6 1371,7 @@ dependencies = [
 "hyper",
 "lazy_static",
 "log",
 "nalgebra",
 "rapier2d",
 "rmp-serde",
 "serde",

M protocol/src/lib.rs => protocol/src/lib.rs +2 -2
@@ 52,7 52,7 @@ pub enum MessageS2C {
    },

    PlanetData {
        planets: Vec<Planet>
        planets: Vec<ProtocolPlanet>
    }
}



@@ 67,7 67,7 @@ pub enum GoodbyeReason {
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Planet {
pub struct ProtocolPlanet {
    pub planet_type: PlanetType,
    pub x: f64,
    pub y: f64,

M server/Cargo.toml => server/Cargo.toml +1 -0
@@ 23,6 23,7 @@ simple_logger = "4.1"
starkingdoms-protocol = { version = "0.1.0", path = "../protocol" }
lazy_static = "1.4.0"
rapier2d = { version = "0.17.2", features = [ "simd-stable" ] }
nalgebra = "0.32.2"

[build-dependencies]
cargo_metadata = "0.15"

M server/src/handler.rs => server/src/handler.rs +21 -5
@@ 1,19 1,23 @@
use std::error::Error;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use futures::stream::{SplitSink, SplitStream};
use futures::{FutureExt, SinkExt, StreamExt};
use hyper::upgrade::Upgraded;
use log::{error, info, warn};
use nalgebra::vector;
use rapier2d::prelude::{RigidBodyBuilder, RigidBodyType, ColliderBuilder};
use tokio::sync::RwLock;
use tokio::sync::mpsc::Receiver;
use tokio_tungstenite::WebSocketStream;
use tungstenite::Message;
use starkingdoms_protocol::{GoodbyeReason, MessageC2S, MessageS2C, Planet, PlanetType, PROTOCOL_VERSION, State};
use starkingdoms_protocol::{GoodbyeReason, MessageC2S, MessageS2C, ProtocolPlanet, PlanetType, PROTOCOL_VERSION, State};
use starkingdoms_protocol::GoodbyeReason::PingPongTimeout;
use crate::manager::{ClientHandlerMessage, ClientManager};
use crate::{send, recv};
use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player};
use crate::{send, recv, SCALE};

pub async fn handle_client(mgr: ClientManager, remote_addr: SocketAddr, mut rx: Receiver<ClientHandlerMessage>, mut client_tx: SplitSink<WebSocketStream<Upgraded>, Message>, mut client_rx: SplitStream<WebSocketStream<Upgraded>>) -> Result<(), Box<dyn Error>> {
pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, remote_addr: SocketAddr, mut rx: Receiver<ClientHandlerMessage>, mut client_tx: SplitSink<WebSocketStream<Upgraded>, Message>, mut client_rx: SplitStream<WebSocketStream<Upgraded>>) -> Result<(), Box<dyn Error>> {
    let mut state = State::Handshake;
    let mut username = String::new();
    let mut ping_timeout = SystemTime::now() + Duration::from_secs(5);


@@ 91,12 95,24 @@ pub async fn handle_client(mgr: ClientManager, remote_addr: SocketAddr, mut rx: 
                            state = next_state;
                            username = requested_username;

                            {
                                let mut data_handle = data.write().await;
                                let player_body = RigidBodyBuilder::new(RigidBodyType::Dynamic)
                                    .translation(vector![0.0, 2100.0/SCALE])
                                    .build();
                                let player_collider = ColliderBuilder::cuboid(1.0 / SCALE, 1.0 / SCALE).build();
                                let player_handle = data_handle.rigid_body_set.insert(player_body);
                                // cannot mutably borrow twice
                                data_handle.collider_set.insert_with_parent(player_collider, player_handle, &mut data_handle.rigid_body_set);
                                mgr.players.write().await.insert(remote_addr, Player { handle: player_handle });
                            }

                            // TODO: Proper planet and position data
                            // TODO: This is only for testing of the planet rendering code
                            // TODO: !!!!!!!!!! REMOVE THIS WHEN PLANETS ACTUALLY EXIST !!!!!!!!!!
                            send!(client_tx, &MessageS2C::PlanetData {
                                planets: vec![
                                    Planet {
                                    ProtocolPlanet {
                                        planet_type: PlanetType::Earth,
                                        radius: 1f64,
                                        x: 0f64,

M server/src/main.rs => server/src/main.rs +26 -5
@@ 3,6 3,9 @@ use std::net::SocketAddr;
use std::sync::Arc;
use hyper::{Body, header, Request, Response, Server, server::conn::AddrStream, StatusCode, upgrade};
use hyper::service::{make_service_fn, service_fn};
use manager::PhysicsData;
use nalgebra::vector;
use rapier2d::prelude::{MultibodyJointSet, ImpulseJointSet, ColliderSet, RigidBodySet, NarrowPhase, BroadPhase, IslandManager, CCDSolver, IntegrationParameters};
use tokio_tungstenite::WebSocketStream;
use tungstenite::{handshake};
use futures::stream::StreamExt;


@@ 11,7 14,7 @@ use log::{error, info, Level};
use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
use starkingdoms_protocol::{PROTOCOL_VERSION};
use crate::manager::{ClientHandler, ClientManager, PhysicsEngine};
use crate::manager::{ClientHandler, ClientManager};
use crate::handler::handle_client;
use crate::timer::timer_main;



@@ 21,7 24,9 @@ pub mod timer;
#[macro_use]
pub mod macros;

async fn handle_request(mut request: Request<Body>, remote_addr: SocketAddr, mgr: ClientManager) -> Result<Response<Body>, Infallible> {
const SCALE: f32 = 1.0 / 10.0;

async fn handle_request(mut request: Request<Body>, remote_addr: SocketAddr, mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>) -> Result<Response<Body>, Infallible> {
    match (request.uri().path(), request.headers().contains_key(header::UPGRADE)) {
        //if the request is ws_echo and the request headers contains an Upgrade key
        ("/ws", true) => {


@@ 64,7 69,7 @@ async fn handle_request(mut request: Request<Body>, remote_addr: SocketAddr, mgr
                                    info!("[{}] passing to client handler", remote_addr);

                                    //forward the stream to the sink to achieve echo
                                    match handle_client(mgr.clone(), remote_addr, rx, ws_write, ws_read).await {
                                    match handle_client(mgr.clone(), physics_data.clone(), remote_addr, rx, ws_write, ws_read).await {
                                        Ok(_) => {},
                                        Err(e) => error!("error on WS connection {}: {}", remote_addr, e),
                                    };


@@ 128,6 133,21 @@ lazy_static! {
        usernames: Arc::new(RwLock::new(Default::default())),
        players: Arc::new(RwLock::new(Default::default())),
    };
    static ref DATA: Arc<RwLock<PhysicsData>> = Arc::new(RwLock::new(PhysicsData { 
        gravity: vector![0.0, 0.0],
        integration_parameters: IntegrationParameters {
            dt: 1.0 / 20.0,
            ..Default::default()
        },
        island_manager: IslandManager::new(),
        broad_phase: BroadPhase::new(),
        narrow_phase: NarrowPhase::new(),
        rigid_body_set: RigidBodySet::new(),
        collider_set: ColliderSet::new(),
        impulse_joint_set: ImpulseJointSet::new(),
        multibody_joint_set: MultibodyJointSet::new(),
        ccd_solver: CCDSolver::new(),
    }));
}

#[tokio::main]


@@ 144,7 164,7 @@ async fn main() {
        async move {
            Ok::<_, Infallible>(service_fn({
                move |request: Request<Body>| {
                    handle_request(request, remote_addr, CMGR.clone())
                    handle_request(request, remote_addr, CMGR.clone(), DATA.clone())
                }
            }))
        }


@@ 152,8 172,9 @@ async fn main() {


    let mgr_timer = CMGR.clone();
    let physics_data = DATA.clone();
    let _timer_thread = tokio::spawn(async move {
        timer_main(mgr_timer).await;
        timer_main(mgr_timer, physics_data).await;
    });

    let server = Server::bind(&addr).serve(make_svc);

M server/src/manager.rs => server/src/manager.rs +24 -9
@@ 3,7 3,8 @@ use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;

use rapier2d::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, EventHandler, PhysicsHooks, RigidBodySet, ColliderSet};
use rapier2d::na::{Vector3, Vector2};
use rapier2d::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, EventHandler, PhysicsHooks, RigidBodySet, ColliderSet, RigidBodyHandle};
use tokio::sync::mpsc::Sender;
use tokio::sync::RwLock;



@@ 16,11 17,7 @@ pub struct ClientManager {

#[derive(Default)]
pub struct Player {
    pub id: u16,
    pub x: f64,
    pub y: f64,
    pub vel_x: f64,
    pub vel_y: f64,
    pub handle: RigidBodyHandle
}

#[derive(Clone)]


@@ 28,10 25,10 @@ pub struct ClientHandler {
    pub tx: Sender<ClientHandlerMessage>
}

pub struct PhysicsEngine {
    pub gravity: Vec<f32>,
#[derive(Clone, Default)]
pub struct PhysicsData {
    pub gravity: Vector2<f32>,
    pub integration_parameters: IntegrationParameters,
    pub pipeline: PhysicsPipeline,
    pub island_manager: IslandManager,
    pub broad_phase: BroadPhase,
    pub narrow_phase: NarrowPhase,


@@ 41,6 38,24 @@ pub struct PhysicsEngine {
    pub multibody_joint_set: MultibodyJointSet,
    pub ccd_solver: CCDSolver,
}
impl PhysicsData {
    pub fn tick(&mut self, pipeline: &mut PhysicsPipeline) {
        pipeline.step(&self.gravity,
                           &self.integration_parameters,
                           &mut self.island_manager,
                           &mut self.broad_phase,
                           &mut self.narrow_phase,
                           &mut self.rigid_body_set,
                           &mut self.collider_set,
                           &mut self.impulse_joint_set,
                           &mut self.multibody_joint_set,
                           &mut self.ccd_solver,
                           None,
                           &(),
                           &()
                        );
    }
}

pub enum ClientHandlerMessage {
    Tick,

M server/src/timer.rs => server/src/timer.rs +8 -19
@@ 1,29 1,18 @@

use std::time::Duration;
use std::{time::Duration, sync::Arc};
use log::{error};

use rapier2d::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet};
use tokio::time::sleep;
use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsEngine};
use rapier2d::prelude::{PhysicsPipeline};
use tokio::{time::sleep, sync::RwLock};
use crate::{manager::{ClientHandlerMessage, ClientManager, PhysicsData}, SCALE};

pub async fn timer_main(mgr: ClientManager) {
    // initialize physics engine
    let mut physics_engine = PhysicsEngine { 
        gravity: vec![0.0, 0.0],
        integration_parameters: IntegrationParameters::default(),
        pipeline: PhysicsPipeline::new(),
        island_manager: IslandManager::new(),
        broad_phase: BroadPhase::new(),
        narrow_phase: NarrowPhase::new(),
        rigid_body_set: RigidBodySet::new(),
        collider_set: ColliderSet::new(),
        impulse_joint_set: ImpulseJointSet::new(),
        multibody_joint_set: MultibodyJointSet::new(),
        ccd_solver: CCDSolver::new(),
    };
pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>) {
    let mut pipeline = PhysicsPipeline::new();
    loop {
        sleep(Duration::from_millis(5)).await;

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

        for (_addr, client_thread) in mgr.handlers.read().await.iter() {
            match client_thread.tx.send(ClientHandlerMessage::Tick).await {
                Ok(_) => (),