use std::{time::Duration, sync::Arc}; use log::{error}; use nalgebra::vector; 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}; pub const ROTATIONAL_FORCE: f64 = 100.0; pub const LATERAL_FORCE: f64 = 100.0; pub async fn timer_main(mgr: ClientManager, physics_data: Arc>, world_data: Arc>) { let mut pipeline = PhysicsPipeline::new(); loop { sleep(Duration::from_millis(5)).await; physics_data.write().await.tick(&mut pipeline); let mut protocol_players = vec![]; { for (player_id, player) in mgr.players.write().await.iter() { let mut physics_data = physics_data.write().await; let player_handle = player.handle; let player_body = physics_data.rigid_body_set.get_mut(player_handle).unwrap(); let planets = world_data.read().await; let grav_force = planets.gravity((player_body.translation().x, player_body.translation().y), player_body.mass()); player_body.add_force(vector![grav_force.0, grav_force.1], true); let mut torque = 0.0; if player.input.right { torque += ROTATIONAL_FORCE; } if player.input.left { torque -= ROTATIONAL_FORCE; } player_body.add_torque(torque, true); let mut lateral = vector![0.0, 0.0]; if player.input.up { lateral -= vector![0.0, LATERAL_FORCE]; } if player.input.down { lateral += vector![0.0, LATERAL_FORCE]; } let rotation = player_body.rotation().clone().angle(); let lateral_rotated = vector![ lateral.x * rotation.cos() - lateral.y * rotation.sin(), lateral.x * rotation.sin() + lateral.y * rotation.cos() ]; player_body.add_force(lateral_rotated, true); let translation = player_body.translation(); let username; { let usernames = mgr.usernames.read().await; username = usernames.get(player_id).unwrap().clone(); } // TODO: Figure out how to adjust codegen to use f64 protocol_players.push(Player { rotation: rotation as f32, x: (translation.x * SCALE) as f32, y: (translation.y * SCALE) as f32, username, special_fields: Default::default(), }); } } let mut to_remove = vec![]; let mut mgr_w = mgr.handlers.write().await; let mgr_r = mgr_w.clone(); for (addr, client_thread) in mgr_r.iter() { match client_thread.tx.send(ClientHandlerMessage::Tick).await { Ok(_) => { 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 planet_data = world.to_protocol(); match client_thread.tx.send(planet_data).await { Ok(_) => (), Err(e) => { error!("unable to send earth packet: {}", e); } }; } Err(e) => { error!("unable to update a client thread: {}", e); to_remove.push(addr); } } } for pending_removal in to_remove { mgr_w.remove(pending_removal); } } }