From 042d48c0414586735443cef771cb1f227fa16461 Mon Sep 17 00:00:00 2001 From: ghostlyzsh Date: Tue, 11 Apr 2023 17:44:43 -0500 Subject: [PATCH] yay broken, player initialization --- Cargo.lock | 1 + protocol/src/lib.rs | 4 ++-- server/Cargo.toml | 1 + server/src/handler.rs | 26 +++++++++++++++++++++----- server/src/main.rs | 31 ++++++++++++++++++++++++++----- server/src/manager.rs | 33 ++++++++++++++++++++++++--------- server/src/timer.rs | 27 ++++++++------------------- 7 files changed, 83 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75b72c40b192a12768e9ef1d81762d2eb5eb1adc..f00f0220c72f2392925ad0dbabb2228010a2ce29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1371,6 +1371,7 @@ dependencies = [ "hyper", "lazy_static", "log", + "nalgebra", "rapier2d", "rmp-serde", "serde", diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index ecc0f10518e355c6f13a7f33ec3aee9ae40bf812..4afc3c80d53ca0b80bba4744322dbac2af9312a0 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -52,7 +52,7 @@ pub enum MessageS2C { }, PlanetData { - planets: Vec + planets: Vec } } @@ -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, diff --git a/server/Cargo.toml b/server/Cargo.toml index 43b5696e663e4a34c6dda5d6423c601eeb3a0bb1..4f535c4f81ccca8419d26c5a378d1a9c95f38cb8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -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" diff --git a/server/src/handler.rs b/server/src/handler.rs index d326580cb52ca9e25cf59d26042d7027fcbfa76e..c710e4d156e6c3c8078bb929e60fbdce65634d9f 100644 --- a/server/src/handler.rs +++ b/server/src/handler.rs @@ -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, mut client_tx: SplitSink, Message>, mut client_rx: SplitStream>) -> Result<(), Box> { +pub async fn handle_client(mgr: ClientManager, data: Arc>, remote_addr: SocketAddr, mut rx: Receiver, mut client_tx: SplitSink, Message>, mut client_rx: SplitStream>) -> Result<(), Box> { 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, diff --git a/server/src/main.rs b/server/src/main.rs index e38980f69970550e4e73f38d982b99e9fa71b74e..aa8918aa0f1081b5998822d778b83e2e6c6b1790 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -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, remote_addr: SocketAddr, mgr: ClientManager) -> Result, Infallible> { +const SCALE: f32 = 1.0 / 10.0; + +async fn handle_request(mut request: Request, remote_addr: SocketAddr, mgr: ClientManager, physics_data: Arc>) -> Result, 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, 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> = 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| { - 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); diff --git a/server/src/manager.rs b/server/src/manager.rs index df311fcf6e136b011b0b28bb48fd5bb367cd31db..eb877f75c5e80e15aa661d25fdfb643033374c57 100644 --- a/server/src/manager.rs +++ b/server/src/manager.rs @@ -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 } -pub struct PhysicsEngine { - pub gravity: Vec, +#[derive(Clone, Default)] +pub struct PhysicsData { + pub gravity: Vector2, 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, diff --git a/server/src/timer.rs b/server/src/timer.rs index 24afa2ea8534ae24083c65711cb92cc62b831b28..7f40bd8a5c469d3e351bea5ceb1b5f3a43b5601f 100644 --- a/server/src/timer.rs +++ b/server/src/timer.rs @@ -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>) { + 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(_) => (),