aboutsummaryrefslogtreecommitdiffstats
path: root/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.rs')
-rw-r--r--src/server.rs174
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());
+ }
+}