use std::f32::consts::PI; use crate::config::planet::Planet; use crate::ecs::{ DragRequestEvent, Part, Player, PlayerThrust, ThrustEvent, }; use crate::server::part::SpawnPartRequest; use crate::server::world_config::WorldConfigResource; use crate::server::{ConnectedGameEntity, ConnectedNetworkEntity}; use bevy::prelude::*; use bevy_rapier2d::prelude::ExternalForce; use bevy_replicon::prelude::FromClient; use crate::server::system_sets::PlayerInputSet; pub fn player_management_plugin(app: &mut App) { app.add_systems(Update, (handle_new_players, player_thrust, dragging).in_set(PlayerInputSet)); } fn dragging( mut events: EventReader>, mut parts: Query<&mut Transform, With>, ) { for event in events.read() { let mut part = parts.get_mut(event.event.0).unwrap(); part.translation.x = event.event.1.x; part.translation.y = event.event.1.y; } } fn handle_new_players( mut commands: Commands, q_new_clients: Query>, world_config: Res, planets: Query<(&Transform, &Planet)>, asset_server: Res, ) { let Some(wc) = &world_config.config else { return; }; for joined_player in &q_new_clients { trace!(?joined_player, "detected joined player!"); // find earth let (spawn_planet_pos, spawn_planet) = planets .iter() .find(|p| p.1.name == wc.hearty.spawn_at) .unwrap_or_else(|| { panic!( "spawn planet {} is missing? (check that the planet is named exactly '{}')", wc.hearty.spawn_at, wc.hearty.spawn_at ) }); let angle = rand::random::() * std::f32::consts::TAU; let offset = spawn_planet.radius + 150.0; let mut new_transform = Transform::from_xyz(angle.cos() * offset, angle.sin() * offset, 0.0); new_transform.rotate_z(angle); new_transform.translation += spawn_planet_pos.translation; info!(?new_transform, ?joined_player, "set player's position!"); commands .entity(joined_player) .insert(new_transform) .insert(SpawnPartRequest( asset_server.load("config/parts/hearty.part.toml"), )) .insert(PlayerThrust::default()) .insert(Player { client: joined_player, }); } } fn player_thrust( mut players: Query<(&Transform, &mut ExternalForce, &mut PlayerThrust), >, clients: Query<&ConnectedNetworkEntity>, mut thrust_event: EventReader>, world_config: Res, ) { for FromClient { client_entity, event, } in thrust_event.read() { let ConnectedNetworkEntity { game_entity } = clients.get(*client_entity).unwrap(); let Ok((_, _, mut thrust)) = players.get_mut(*game_entity) else { continue; }; match *event { ThrustEvent::Up(on) => thrust.up = on, ThrustEvent::Down(on) => thrust.down = on, ThrustEvent::Left(on) => thrust.left = on, ThrustEvent::Right(on) => thrust.right = on, } } for (transform, mut force, thrust) in &mut players { let Some(world_config) = &world_config.config else { return; }; let forward = (transform.rotation * Vec3::Y).xy(); let mut external_force = ExternalForce::default(); let mut thrusters = [0.0; 4]; // counterclockwise wrt +y axis if thrust.up { thrusters[1] = 1.0; thrusters[2] = 1.0; } if thrust.down { thrusters[0] = 1.0; thrusters[3] = 1.0; } if thrust.left { thrusters[0] = 1.0; thrusters[2] = 1.0; } if thrust.right { thrusters[1] = 1.0; thrusters[3] = 1.0; } let half_size = Vec2::new( world_config.part.default_width / 2.0, world_config.part.default_height / 2.0, ) .length(); external_force += ExternalForce::at_point( -forward * thrusters[0] * world_config.hearty.thrust, transform.translation.xy() + half_size * Vec2::new((1.0 * PI / 4.0).cos(), (1.0 * PI / 4.0).sin()).rotate(forward), transform.translation.xy(), ); external_force += ExternalForce::at_point( forward * thrusters[1] * world_config.hearty.thrust, transform.translation.xy() + half_size * Vec2::new((3.0 * PI / 4.0).cos(), (3.0 * PI / 4.0).sin()).rotate(forward), transform.translation.xy(), ); external_force += ExternalForce::at_point( forward * thrusters[2] * world_config.hearty.thrust, transform.translation.xy() + half_size * Vec2::new((5.0 * PI / 4.0).cos(), (5.0 * PI / 4.0).sin()).rotate(forward), transform.translation.xy(), ); external_force += ExternalForce::at_point( -forward * thrusters[3] * world_config.hearty.thrust, transform.translation.xy() + half_size * Vec2::new((7.0 * PI / 4.0).cos(), (7.0 * PI / 4.0).sin()).rotate(forward), transform.translation.xy(), ); *force += external_force; } }