M server/Cargo.toml => server/Cargo.toml +1 -1
@@ 27,4 27,4 @@ rapier2d-f64 = { version = "0.17.2", features = [ "simd-stable" ] }
nalgebra = "0.32.2"
[build-dependencies]
-cargo_metadata = "0.15">
\ No newline at end of file
+cargo_metadata = "0.15"
A server/src/entity.rs => server/src/entity.rs +117 -0
@@ 0,0 1,117 @@
+use std::{sync::atomic::AtomicU32, collections::HashMap, net::SocketAddr};
+
+use nalgebra::Vector2;
+use starkingdoms_protocol::planet::PlanetType;
+
+use crate::{planet::Planet, SCALE, manager::{ClientHandlerMessage, Player}};
+
+pub type EntityId = u32;
+pub type Entities = HashMap<EntityId, Entity>;
+static mut ENTITY_ID_COUNT: AtomicU32 = AtomicU32::new(0);
+pub fn get_entity_id() -> EntityId {
+ let last_entity_id = unsafe { &ENTITY_ID_COUNT };
+ let id = last_entity_id.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
+ if id > 2_147_483_600 { panic!("No remaining entity ids") };
+ id
+}
+
+pub struct EntityHandler {
+ pub entities: Entities,
+}
+
+impl EntityHandler {
+ pub fn new() -> EntityHandler {
+ EntityHandler {
+ entities: Entities::new()
+ }
+ }
+ pub fn get_planets(&self) -> Vec<Planet> {
+ let mut ids = Vec::new();
+ for entity in self.entities.values() {
+ if let Entity::Planet(planet) = entity {
+ ids.push(planet.clone());
+ }
+ }
+ ids
+ }
+ pub fn get_planet(&self, planet_type: PlanetType) -> Option<Planet> {
+ let mut planets = self.get_planets();
+ for i in 0..planets.len() {
+ if planets[i].planet_type == planet_type {
+ planets.remove(i);
+ }
+ }
+ if planets.len() == 0 {
+ return None;
+ }
+ Some(planets[0].clone())
+ }
+
+ pub fn get_players(&self) -> Vec<(SocketAddr, Player)> {
+ let mut players = Vec::new();
+ for entity in self.entities.values() {
+ if let Entity::Player(player) = entity {
+ players.push((player.addr, player.clone()));
+ }
+ }
+ players
+ }
+ pub fn get_player_id(&self, addr: SocketAddr) -> Option<EntityId> {
+ for (id, entity) in self.entities.iter() {
+ if let Entity::Player(player) = entity {
+ if player.addr == addr {
+ return Some(*id);
+ }
+ }
+ }
+ None
+ }
+ pub fn get_player(&self, addr: SocketAddr) -> Option<Player> {
+ let mut players = self.get_players();
+ for i in 0..players.len() {
+ if players[i].0 != addr {
+ players.remove(i);
+ }
+ }
+ if players.len() == 0 {
+ return None;
+ }
+ Some(players[0].clone().1)
+ }
+
+ pub fn gravity(&self, position: (f64, f64), mass: f64) -> (f64, f64) {
+ let mut direction = Vector2::zeros();
+ let planets = self.get_planets();
+ for planet in planets.clone() {
+ let planet_grav = planet.gravity(position, mass);
+ direction.x += planet_grav.0;
+ direction.y += planet_grav.1;
+ }
+ (direction.x, direction.y)
+ }
+
+ pub fn to_protocol(&self) -> ClientHandlerMessage {
+ let mut planets = vec![];
+
+ for planet in self.get_planets().clone() {
+ // TODO: Adjust codegen to use f64
+ planets.push(starkingdoms_protocol::planet::Planet {
+ planet_type: planet.planet_type.into(),
+ x: (planet.position.0 * SCALE) as f32,
+ y: (planet.position.1 * SCALE) as f32,
+ radius: planet.radius as f32, // DO NOT * SCALE
+ special_fields: Default::default(),
+ });
+ }
+
+ ClientHandlerMessage::PlanetData {
+ planets
+ }
+ }
+}
+
+#[derive(Clone)]
+pub enum Entity {
+ Player(Player),
+ Planet(Planet),
+}
M server/src/handler.rs => server/src/handler.rs +23 -9
@@ 4,7 4,7 @@ use std::sync::Arc;
use std::time::{Duration, SystemTime};
use futures::stream::{SplitSink, SplitStream};
use futures::{FutureExt, SinkExt, StreamExt};
-use log::{error, info};
+use log::{error, info, debug};
use nalgebra::{vector, point};
use rapier2d_f64::prelude::{RigidBodyBuilder, RigidBodyType, ColliderBuilder, MassProperties, Collider};
use tungstenite::Message;
@@ 12,13 12,17 @@ use starkingdoms_protocol::goodbye_reason::GoodbyeReason;
use starkingdoms_protocol::message_s2c::{MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong};
use starkingdoms_protocol::{MessageS2C, MessageC2S, PROTOCOL_VERSION};
use starkingdoms_protocol::state::State;
+use crate::entity::{EntityHandler, get_entity_id, Entity};
use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player};
use crate::{send, recv, SCALE};
use async_std::{sync::RwLock, channel::Receiver};
use async_std::net::TcpStream;
use async_tungstenite::WebSocketStream;
-pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, remote_addr: SocketAddr, rx: Receiver<ClientHandlerMessage>, mut client_tx: SplitSink<WebSocketStream<TcpStream>, Message>, mut client_rx: SplitStream<WebSocketStream<TcpStream>>) -> Result<(), Box<dyn Error>> {
+pub async fn handle_client(mgr: ClientManager, entities: Arc<RwLock<EntityHandler>>, data: Arc<RwLock<PhysicsData>>,
+ remote_addr: SocketAddr, rx: Receiver<ClientHandlerMessage>,
+ mut client_tx: SplitSink<WebSocketStream<TcpStream>, Message>, mut client_rx: SplitStream<WebSocketStream<TcpStream>>
+ ) -> Result<(), Box<dyn Error>> {
let mut state = State::Handshake;
let mut username = String::new();
let mut ping_timeout = SystemTime::now() + Duration::from_secs(10);
@@ 148,7 152,13 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
data_handle.rigid_body_set = rigid_body_set;
data_handle.collider_set = collider_set;
- mgr.players.write().await.insert(remote_addr, Player { handle: player_handle, input: Default::default() });
+ entities.write().await.entities.insert(get_entity_id(),
+ Entity::Player(Player {
+ handle: player_handle,
+ input: Default::default(),
+ addr: remote_addr
+ }));
+ debug!("running");
}
},
MessageC2S::Goodbye(pkt) => {
@@ 201,12 211,16 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
ping_timeout = SystemTime::now() + Duration::from_secs(10);
},
MessageC2S::Input(p) => {
- let mut players = mgr.players.write().await;
- let me = players.get_mut(&remote_addr).expect("player disconnected but continued to send packets");
- me.input.up = p.up_pressed;
- me.input.down = p.down_pressed;
- me.input.left = p.left_pressed;
- me.input.right = p.right_pressed;
+ let mut handle = entities.write().await;
+ let mut id = handle.get_player_id(remote_addr)
+ .expect("could not get player id");
+ if let Entity::Player(ref mut me) = handle.entities.get_mut(&id)
+ .expect("player disconnected but continued to send packets") {
+ me.input.up = p.up_pressed;
+ me.input.down = p.down_pressed;
+ me.input.left = p.left_pressed;
+ me.input.right = p.right_pressed;
+ }
}
}
}
M server/src/main.rs => server/src/main.rs +25 -156
@@ 3,6 3,7 @@ use std::net::SocketAddr;
use async_std::io::WriteExt;
use async_std::sync::Arc;
use async_std::net::{TcpListener, TcpStream};
+use entity::{Entities, EntityHandler};
use manager::PhysicsData;
use nalgebra::vector;
use planet::Planets;
@@ 10,6 11,7 @@ use rapier2d_f64::prelude::{MultibodyJointSet, ImpulseJointSet, ColliderSet, Rig
use lazy_static::lazy_static;
use log::{error, info, Level, warn};
use serde::{Deserialize, Serialize};
+use crate::entity::Entity;
use crate::manager::{ClientHandler, ClientManager};
use crate::timer::timer_main;
use async_std::sync::RwLock;
@@ 24,11 26,13 @@ pub mod timer;
pub mod macros;
pub mod planet;
pub mod orbit;
+pub mod entity;
const SCALE: f64 = 1.0;
-async fn handle_request(conn: TcpStream, remote_addr: SocketAddr, mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>) {
- match _handle_request(conn, remote_addr, mgr, physics_data).await {
+async fn handle_request(conn: TcpStream, remote_addr: SocketAddr, mgr: ClientManager,
+ entities: Arc<RwLock<EntityHandler>>, physics_data: Arc<RwLock<PhysicsData>>) {
+ match _handle_request(conn, remote_addr, mgr, entities, physics_data).await {
Ok(_) => (),
Err(e) => {
error!("[{}] error in handler thread: {}", remote_addr, e);
@@ 36,7 40,8 @@ async fn handle_request(conn: TcpStream, remote_addr: SocketAddr, mgr: ClientMan
}
}
-async fn _handle_request(mut conn: TcpStream, remote_addr: SocketAddr, mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>) -> Result<(), Box<dyn Error>> {
+async fn _handle_request(mut conn: TcpStream, remote_addr: SocketAddr, mgr: ClientManager,
+ entities: Arc<RwLock<EntityHandler>>, physics_data: Arc<RwLock<PhysicsData>>) -> Result<(), Box<dyn Error>> {
let mut peek_buf = [0u8; 9];
loop {
@@ 84,7 89,7 @@ async fn _handle_request(mut conn: TcpStream, remote_addr: SocketAddr, mgr: Clie
info!("[{}] passing to client handler", remote_addr);
//forward the stream to the sink to achieve echo
- match handle_client(mgr.clone(), physics_data.clone(), remote_addr, rx, ws_write, ws_read).await {
+ match handle_client(mgr.clone(), entities.clone(), physics_data.clone(), remote_addr, rx, ws_write, ws_read).await {
Ok(_) => (),
Err(e) if e.is::<async_tungstenite::tungstenite::error::Error>() => {
let e = e.downcast::<async_tungstenite::tungstenite::error::Error>().unwrap();
@@ 110,160 115,38 @@ async fn _handle_request(mut conn: TcpStream, remote_addr: SocketAddr, mgr: Clie
let mut collider_set = data.collider_set.clone();
let mut impulse_joint_set = data.impulse_joint_set.clone();
let mut multibody_joint_set = data.multibody_joint_set.clone();
- let handle = match mgr.players.read().await.get(&remote_addr) {
- Some(s) => s.handle,
+ let player_id = match entities.read().await.get_player_id(remote_addr) {
+ Some(s) => s,
None => {
- warn!("[{}] player missing from mgr.players", remote_addr);
- return Err("Player missing from mgr.players".into());
+ warn!("[{}] player missing from entities.players", remote_addr);
+ return Err("Player missing from entities.players".into());
}
};
- rigid_body_set.remove(handle, &mut island_manager, &mut collider_set,
- &mut impulse_joint_set, &mut multibody_joint_set, true);
+ if let Entity::Player(player) = entities.read().await.entities.get(&player_id).unwrap() {
+ rigid_body_set.remove(player.handle, &mut island_manager, &mut collider_set,
+ &mut impulse_joint_set, &mut multibody_joint_set, true);
+ }
data.rigid_body_set = rigid_body_set;
data.collider_set = collider_set;
data.island_manager = island_manager;
data.impulse_joint_set = impulse_joint_set;
data.multibody_joint_set = multibody_joint_set;
- mgr.players.write().await.remove(&remote_addr);
+ entities.write().await.entities.remove(&player_id);
}
Ok(())
}
-/*
-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) => {
- info!("received connection from {}", remote_addr);
- //assume request is a handshake, so create the handshake response
- let response =
- match handshake::server::create_response_with_body(&request, Body::empty) {
- Ok(response) => {
- //in case the handshake response creation succeeds,
- //spawn a task to handle the websocket connection
- tokio::spawn(async move {
- //using the hyper feature of upgrading a connection
- match upgrade::on(&mut request).await {
- //if successfully upgraded
- Ok(upgraded) => {
- info!("[{}] connection upgraded", remote_addr);
- //create a websocket stream from the upgraded object
- let ws_stream = WebSocketStream::from_raw_socket(
- //pass the upgraded object
- //as the base layer stream of the Websocket
- upgraded,
- tungstenite::protocol::Role::Server,
- None,
- ).await;
-
- //we can split the stream into a sink and a stream
- let (ws_write, ws_read) = ws_stream.split();
-
- let (tx, rx) = tokio::sync::mpsc::channel(128);
-
- let client = ClientHandler {
- tx,
- };
-
- // Acquire the write lock in a small scope, so it's dropped as quickly as possible
- {
- mgr.handlers.write().await.insert(remote_addr, client);
- }
-
- info!("[{}] passing to client handler", remote_addr);
-
- //forward the stream to the sink to achieve echo
- 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),
- };
-
- // clean up values left over
- {
- mgr.handlers.write().await.remove(&remote_addr);
- mgr.usernames.write().await.remove(&remote_addr);
- // remove player physics body
- let mut data = physics_data.write().await;
- let mut rigid_body_set = data.rigid_body_set.clone();
- let mut island_manager = data.island_manager.clone();
- let mut collider_set = data.collider_set.clone();
- let mut impulse_joint_set = data.impulse_joint_set.clone();
- let mut multibody_joint_set = data.multibody_joint_set.clone();
- let handle = match mgr.players.read().await.get(&remote_addr) {
- Some(s) => s.handle,
- None => {error!("looks like somebody forgot to make their player"); return}
- };
- rigid_body_set.remove(handle, &mut island_manager, &mut collider_set,
- &mut impulse_joint_set, &mut multibody_joint_set, true);
- data.rigid_body_set = rigid_body_set;
- data.collider_set = collider_set;
- data.island_manager = island_manager;
- data.impulse_joint_set = impulse_joint_set;
- data.multibody_joint_set = multibody_joint_set;
- mgr.players.write().await.remove(&remote_addr);
- }
- },
- Err(e) => {
- error!("error upgrading connection from {} to WS: {}", remote_addr, e);
- }
- }
- });
- //return the response to the handshake request
- response
- },
- Err(e) => {
- //probably the handshake request is not up to spec for websocket
- error!("error creating websocket response to {}: {}", remote_addr, e);
- let mut res = Response::new(Body::from(format!("Failed to create websocket: {}", e)));
- *res.status_mut() = StatusCode::BAD_REQUEST;
- return Ok(res);
- }
- };
-
- Ok::<_, Infallible>(response)
- },
- ("/ws", false) => {
- Ok(Response::builder().status(400).body(Body::from("Connection-Upgrade header missing")).unwrap())
- },
- ("/ping", false) => {
- Ok(Response::builder().status(200).header("Access-Control-Allow-Origin", "*").body(Body::from(
- serde_json::to_string(&ServerPingResponse {
- version: ServerPingResponseVersion {
- name: env!("STK_VERSION_NAME").to_string(), // Set by build.rs
- number: env!("STK_VERSION").to_string(), // Set by build.rs
- protocol: PROTOCOL_VERSION,
- },
- players: CMGR.usernames.read().await.len() as u32,
- description: env!("STK_SLP_DESCRIPTION").to_string(),
- }).unwrap()
- )).unwrap())
- },
- (_url, false) => {
- // typical HTTP file request
- // TODO
- Ok(Response::new(Body::empty()))
- },
- (_, true) => {
- // http upgrade on non-/ws endpoint
- Ok(Response::builder().status(400).body(Body::from("Incorrect WebSocket endpoint")).unwrap())
- }
- }
-}
-*/
-
lazy_static! {
static ref CMGR: ClientManager = ClientManager {
handlers: Arc::new(RwLock::new(Default::default())),
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()
- },
+ ..Default::default() },
island_manager: IslandManager::new(),
broad_phase: BroadPhase::new(),
narrow_phase: NarrowPhase::new(),
@@ 271,9 154,8 @@ lazy_static! {
collider_set: ColliderSet::new(),
impulse_joint_set: ImpulseJointSet::new(),
multibody_joint_set: MultibodyJointSet::new(),
- ccd_solver: CCDSolver::new(),
- }));
- static ref PLANETS: Arc<RwLock<Planets>> = Arc::new(RwLock::new(Planets::default()));
+ ccd_solver: CCDSolver::new(), }));
+ static ref ENTITIES: Arc<RwLock<EntityHandler>> = Arc::new(RwLock::new(EntityHandler::new()));
}
#[async_std::main]
@@ 284,25 166,11 @@ async fn main() {
info!("Listening on {} for HTTP/WebSocket connections", addr);
- // make earth
- {
- let mut data_handle = DATA.write().await;
-
- let mut rigid_body_set = data_handle.rigid_body_set.clone();
- let mut collider_set = data_handle.collider_set.clone();
-
- let mut planets = PLANETS.write().await;
- planets.planets = Planets::new(&mut rigid_body_set, &mut collider_set).planets;
-
- data_handle.rigid_body_set = rigid_body_set;
- data_handle.collider_set = collider_set;
- }
-
let mgr_timer = CMGR.clone();
let physics_data = DATA.clone();
- let world_data = PLANETS.clone();
+ let entities_timer = ENTITIES.clone();
let _timer_thread = async_std::task::spawn(async move {
- timer_main(mgr_timer, physics_data, world_data).await;
+ timer_main(mgr_timer, physics_data, entities_timer).await;
});
let try_socket = TcpListener::bind(&addr).await;
@@ 316,7 184,8 @@ async fn main() {
};
while let Ok((stream, peer_addr)) = listener.accept().await {
- async_std::task::spawn(handle_request(stream, peer_addr, CMGR.clone(), DATA.clone()));
+ async_std::task::spawn(handle_request(stream, peer_addr, CMGR.clone(),
+ ENTITIES.clone(), DATA.clone()));
}
}
M server/src/manager.rs => server/src/manager.rs +5 -5
@@ 1,7 1,7 @@
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;
-use rapier2d_f64::na::{Vector2};
+use rapier2d_f64::na::Vector2;
use rapier2d_f64::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet, RigidBodyHandle};
use async_std::sync::RwLock;
use async_std::channel::Sender;
@@ 10,16 10,16 @@ use async_std::channel::Sender;
pub struct ClientManager {
pub handlers: Arc<RwLock<HashMap<SocketAddr, ClientHandler>>>,
pub usernames: Arc<RwLock<HashMap<SocketAddr, String>>>,
- pub players: Arc<RwLock<HashMap<SocketAddr, Player>>>
}
-#[derive(Default)]
+#[derive(Clone)]
pub struct Player {
pub handle: RigidBodyHandle,
- pub input: PlayerInput
+ pub input: PlayerInput,
+ pub addr: SocketAddr,
}
-#[derive(Default)]
+#[derive(Default, Clone)]
pub struct PlayerInput {
pub up: bool,
pub left: bool,
M server/src/planet.rs => server/src/planet.rs +29 -16
@@ 1,8 1,11 @@
use std::collections::HashMap;
+use std::sync::Arc;
+use async_std::sync::RwLock;
use nalgebra::{Vector2, vector};
use rapier2d_f64::prelude::{RigidBodyHandle, RigidBodySet, ColliderBuilder, RigidBodyBuilder, ColliderSet};
use starkingdoms_protocol::planet::PlanetType;
+use crate::entity::{Entities, get_entity_id, Entity, EntityId, EntityHandler};
use crate::{SCALE, manager::ClientHandlerMessage};
use crate::orbit::constants::{EARTH_MASS, EARTH_RADIUS, MOON_APOAPSIS, MOON_MASS, MOON_PERIAPSIS, MOON_RADIUS};
use crate::orbit::orbit::{calculate_point_on_orbit, calculate_world_position_of_orbit};
@@ 43,7 46,10 @@ impl Planets {
self.planets.get_mut(planet_id)
}
- pub fn make_planet(planets: &mut HashMap<String, Planet>, planet_id: &str, planet_type: PlanetType, mass: f64, radius: f64, position: (f64, f64), rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet) {
+ pub async fn make_planet(planet_id: &str,
+ planet_type: PlanetType, mass: f64, radius: f64,
+ position: (f64, f64), rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet
+ ) -> (EntityId, Entity) {
let collider = ColliderBuilder::ball(radius / SCALE)
.build();
let body = RigidBodyBuilder::dynamic()
@@ 54,20 60,20 @@ impl Planets {
collider_set.insert_with_parent(collider, body_handle, rigid_body_set);
- planets.insert(planet_id.to_string(), Planet {
+ let entity_id = get_entity_id();
+ (entity_id, Entity::Planet(Planet {
planet_type,
body_handle,
position,
radius,
mass,
- });
+ }))
}
- pub fn new(rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet) -> Planets {
- let mut planets = HashMap::new();
-
- Planets::make_planet(
- &mut planets,
+ pub async fn new(rigid_body_set: &mut RigidBodySet, collider_set: &mut ColliderSet,
+ entities: &mut Entities) -> Vec<EntityId> {
+ let mut planet_ids: Vec<EntityId> = Vec::new();
+ let (earth_id, entity) = Planets::make_planet(
"earth",
PlanetType::Earth,
EARTH_MASS,
@@ 75,12 81,18 @@ impl Planets {
(100.0, 100.0),
rigid_body_set,
collider_set,
- );
-
- let moon_start_point = calculate_world_position_of_orbit(calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, 0.0), vector![planets.get("earth").unwrap().position.0, planets.get("earth").unwrap().position.1]);
+ ).await;
+ entities.insert(earth_id, entity);
+ planet_ids.push(earth_id);
+
+ let moon_start_point;
+ if let Entity::Planet(earth) = entities.get(&earth_id).unwrap() {
+ moon_start_point = calculate_world_position_of_orbit(calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, 0.0), vector![earth.position.0, earth.position.1]);
+ } else {
+ moon_start_point = vector![0., 0.];
+ }
- Planets::make_planet(
- &mut planets,
+ let (moon_id, moon) = Planets::make_planet(
"moon",
PlanetType::Moon,
MOON_MASS,
@@ 88,9 100,10 @@ impl Planets {
(moon_start_point[0], moon_start_point[1]),
rigid_body_set,
collider_set
- );
-
- Planets { planets }
+ ).await;
+ entities.insert(moon_id, moon);
+ planet_ids.push(moon_id);
+ planet_ids
}
pub fn to_protocol(&self) -> ClientHandlerMessage {
M server/src/timer.rs => server/src/timer.rs +26 -10
@@ 4,18 4,31 @@ use nalgebra::{vector, point};
use rapier2d_f64::prelude::{PhysicsPipeline};
use async_std::sync::RwLock;
use async_std::task::sleep;
-use starkingdoms_protocol::player::Player;
-use crate::{manager::{ClientHandlerMessage, ClientManager, PhysicsData}, SCALE, planet::Planets};
+use starkingdoms_protocol::{player::Player, planet::PlanetType};
+use crate::{manager::{ClientHandlerMessage, ClientManager, PhysicsData}, SCALE, planet::{Planets, Planet}, entity::{Entities, Entity, EntityHandler}};
use crate::orbit::constants::{EARTH_MASS, GAME_ORBITS_ENABLED, MOON_APOAPSIS, MOON_MASS, MOON_ORBIT_TIME, MOON_PERIAPSIS};
use crate::orbit::orbit::{calculate_point_on_orbit, calculate_vector_of_orbit, calculate_world_position_of_orbit};
pub const ROTATIONAL_FORCE: f64 = 100.0;
pub const LATERAL_FORCE: f64 = 100.0;
-pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>, world_data: Arc<RwLock<Planets>>) {
+pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>, entities: Arc<RwLock<EntityHandler>>) {
let mut pipeline = PhysicsPipeline::new();
let mut time = 0.0;
+ let planet_ids;
+
+ {
+ let mut data_handle = physics_data.write().await;
+
+ let mut rigid_body_set = data_handle.rigid_body_set.clone();
+ let mut collider_set = data_handle.collider_set.clone();
+
+ planet_ids = Planets::new(&mut rigid_body_set, &mut collider_set, &mut entities.write().await.entities).await;
+
+ data_handle.rigid_body_set = rigid_body_set;
+ data_handle.collider_set = collider_set;
+ }
loop {
sleep(Duration::from_millis(5)).await;
@@ 28,19 41,22 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData
// IT MAY ALWAYS BE TRUE
// THATS FINE
if GAME_ORBITS_ENABLED {
- let mut planets = world_data.write().await;
+ let mut planets = entities.write().await;
// update earth (nothing changes, yet)
- let new_earth_position = vector![planets.get_planet("earth").unwrap().position.0, planets.get_planet("earth").unwrap().position.1];
+ let new_earth_position;
+ let earth = planets.get_planet(PlanetType::Earth).unwrap();
+ new_earth_position = vector![earth.position.0, earth.position.1];
// update moon
+ let moon: &mut Planet = &mut planets.get_planet(PlanetType::Moon).unwrap();
let new_moon_position = calculate_world_position_of_orbit(calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, time / MOON_ORBIT_TIME), new_earth_position);
- let moon_body = physics_data.rigid_body_set.get_mut(planets.get_planet_mut("moon").unwrap().body_handle).unwrap();
+ let moon_body = physics_data.rigid_body_set.get_mut(moon.body_handle).unwrap();
let moon_force = calculate_vector_of_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, time / MOON_ORBIT_TIME, moon_body.translation().x, moon_body.translation().y, new_earth_position[0], new_earth_position[1],MOON_MASS, 1f64 / 20f64);
moon_body.reset_forces(true);
moon_body.add_force(moon_force, true);
//moon_body.set_linvel(moon_force, true);
- planets.get_planet_mut("moon").unwrap().position = (moon_body.translation()[0] / SCALE, moon_body.translation()[1] / SCALE);
+ moon.position = (moon_body.translation()[0] / SCALE, moon_body.translation()[1] / SCALE);
}
physics_data.tick(&mut pipeline);
@@ 48,12 64,12 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData
let mut protocol_players = vec![];
{
- for (player_id, player) in mgr.players.write().await.iter() {
+ for (player_id, player) in entities.read().await.get_players().iter() {
let player_handle = player.handle;
let player_body = physics_data.rigid_body_set.get_mut(player_handle).unwrap();
player_body.reset_forces(true);
player_body.reset_torques(true);
- let planets = world_data.read().await;
+ let planets = entities.read().await;
let grav_force = planets.gravity((player_body.translation().x, player_body.translation().y), player_body.mass());
player_body.apply_impulse(vector![grav_force.0, grav_force.1], true);
@@ 167,7 183,7 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData
}
};
- let world = world_data.read().await;
+ let world = entities.read().await;
let planet_data = world.to_protocol();
match client_thread.tx.send(planet_data).await {
Ok(_) => (),