diff options
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 174 |
1 files changed, 156 insertions, 18 deletions
diff --git a/src/server.rs b/src/server.rs index 188aad1..52daf1a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,8 +1,11 @@ use crate::protocol::*; use crate::server::network::*; +use crate::shared::cooldown::*; use crate::shared::imperative::*; +use crate::shared::projectile::*; use crate::shared::*; use bevy::prelude::*; +use bevy::utils::Duration; use bevy::utils::HashMap; use lightyear::prelude::*; use rand::Rng; @@ -29,22 +32,43 @@ impl Plugin for ServerPlugin { .add_plugins(NetworkPlugin { transport: self.transport.clone(), }) - .add_systems(Update, connections) - .add_systems(FixedUpdate, player_input) - .add_systems(Update, imperative); + .add_systems(Startup, setup) + .add_systems(Update, (connects, disconnects)) + .add_systems( + Update, + ( + imperative_attack.after(cooldown_decrement), + imperative_walk_to, + ) + .after(player_input), + ) + .add_systems( + Update, + ( + projectile_move.after(imperative_walk_to), + projectile_despawn, + ) + .chain(), + ) + .add_systems(Update, cooldown_decrement) + .add_systems(FixedUpdate, player_input); } } -fn connections( +fn setup(mut commands: Commands, mut entity_map: ResMut<EntityMap>) { + let client_id = 1; + let entity = commands.spawn(PlayerBundle::new(1, Vec2::ZERO, Color::GRAY)); + entity_map.0.insert(client_id, entity.id()); +} + +fn connects( mut commands: Commands, mut connects: EventReader<server::ConnectEvent>, - mut disconnects: EventReader<server::DisconnectEvent>, mut entity_map: ResMut<EntityMap>, ) { let mut rng = rand::thread_rng(); for connection in connects.read() { let client_id = connection.context(); - info!("connected: {:?}", client_id); let position = Vec2::new( 50. * rng.gen_range(-2..=2) as f32, 50. * rng.gen_range(-2..=2) as f32, @@ -53,9 +77,15 @@ fn connections( let entity = commands.spawn(PlayerBundle::new(*client_id, position, color)); entity_map.0.insert(*client_id, entity.id()); } +} + +fn disconnects( + mut commands: Commands, + mut disconnects: EventReader<server::DisconnectEvent>, + mut entity_map: ResMut<EntityMap>, +) { for connection in disconnects.read() { let client_id = connection.context(); - info!("disconnected: {:?}", client_id); if let Some(entity_id) = entity_map.0.remove(client_id) { commands.entity(entity_id).despawn(); } @@ -86,22 +116,130 @@ fn player_input( const MOVEMENT_SPEED: f32 = 80.; -fn imperative(mut players: Query<(&mut Imperative, &mut PlayerPosition)>, time: Res<Time>) { - for (mut imperative, mut position) in players.iter_mut() { +fn imperative_walk_to( + mut players: Query<(Entity, &mut Imperative)>, + mut positions: Query<&mut PlayerPosition>, + time: Res<Time>, +) { + for (entity, mut imperative) in players.iter_mut() { match *imperative { - Imperative::Idle => {} - Imperative::WalkTo(target) => { - let distance = (target - position.0).length(); - let direction = (target - position.0).normalize_or_zero(); - let new_position = position.0 - + f32::min(MOVEMENT_SPEED * time.delta().as_secs_f32(), distance) * direction; - if position.0.distance(new_position) < f32::EPSILON { - position.0 = target; + Imperative::WalkTo(target_position) => { + if let Ok(mut position) = positions.get_mut(entity) { + let distance = (target_position - position.0).length(); + let direction = (target_position - position.0).normalize_or_zero(); + let new_position = position.0 + + f32::min(MOVEMENT_SPEED * time.delta().as_secs_f32(), distance) + * direction; + if position.0.distance(new_position) < f32::EPSILON { + position.0 = target_position; + *imperative = Imperative::Idle; + } else { + position.0 = new_position; + } + } else { *imperative = Imperative::Idle; + } + } + _ => {} + } + } +} + +fn imperative_attack( + entity_map: Res<EntityMap>, + mut commands: Commands, + mut cooldowns: Query<&mut Cooldown>, + mut players: Query<(&PlayerId, &mut Imperative)>, + positions: Query<&PlayerPosition>, +) { + for (id, mut imperative) in players.iter_mut() { + match *imperative { + Imperative::Attack(target_player) => { + if let Some(entity) = entity_map.0.get(&id.0) { + if let Ok(position) = positions.get(*entity) { + if let Ok(mut cooldown) = cooldowns.get_mut(*entity) { + if cooldown.a_cooldown.is_zero() { + cooldown.a_cooldown = Duration::from_secs_f32(1.5); + commands.spawn(ProjectileBundle { + projectile: Projectile { + target_player, + source_player: *id, + }, + position: ProjectilePosition(position.0), + replicate: Replicate::default(), + }); + } + } else { + *imperative = Imperative::Idle; + } + } else { + *imperative = Imperative::Idle; + } } else { - position.0 = new_position; + *imperative = Imperative::Idle; + } + } + _ => {} + } + } +} + +const PROJECTILE_SPEED: f32 = 150.; + +fn projectile_move( + entity_map: Res<EntityMap>, + mut projectile_positions: Query<&mut ProjectilePosition>, + player_positions: Query<&PlayerPosition>, + projectiles: Query<(Entity, &mut Projectile)>, + time: Res<Time>, +) { + for (entity, projectile) in projectiles.iter() { + if let Some(target_entity) = entity_map.0.get(&projectile.target_player.0) { + if let Ok(mut position) = projectile_positions.get_mut(entity) { + if let Ok(target_position) = player_positions.get(*target_entity) { + let distance = (target_position.0 - position.0).length(); + let direction = (target_position.0 - position.0).normalize_or_zero(); + let new_position = position.0 + + f32::min(PROJECTILE_SPEED * time.delta().as_secs_f32(), distance) + * direction; + if position.0.distance(new_position) < f32::EPSILON { + position.0 = target_position.0; + } else { + position.0 = new_position; + } + } + } + } + } +} + +fn projectile_despawn( + entity_map: Res<EntityMap>, + mut commands: Commands, + projectile_positions: Query<&ProjectilePosition>, + player_positions: Query<&PlayerPosition>, + projectiles: Query<(Entity, &mut Projectile)>, +) { + for (entity, projectile) in projectiles.iter() { + if let Some(target_entity) = entity_map.0.get(&projectile.target_player.0) { + if let Ok(position) = projectile_positions.get(entity) { + if let Ok(target_position) = player_positions.get(*target_entity) { + if position.0.distance(target_position.0) < f32::EPSILON { + commands.entity(entity).despawn(); + } } } } } } + +fn cooldown_decrement(mut cooldowns: Query<&mut Cooldown>, time: Res<Time>) { + for mut cooldown in cooldowns.iter_mut() { + cooldown.a_cooldown = cooldown.a_cooldown.saturating_sub(time.delta()); + cooldown.q_cooldown = cooldown.q_cooldown.saturating_sub(time.delta()); + cooldown.w_cooldown = cooldown.w_cooldown.saturating_sub(time.delta()); + cooldown.e_cooldown = cooldown.e_cooldown.saturating_sub(time.delta()); + cooldown.d_cooldown = cooldown.d_cooldown.saturating_sub(time.delta()); + cooldown.f_cooldown = cooldown.f_cooldown.saturating_sub(time.delta()); + } +} |