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<RwLock<PhysicsData>>, world_data: Arc<RwLock<Planets>>) {
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(),
});
}
}
for (_addr, client_thread) in mgr.handlers.read().await.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);
}
}
}
}
}