diff options
-rw-r--r-- | shell.nix | 20 | ||||
-rw-r--r-- | src/client.rs | 78 | ||||
-rw-r--r-- | src/protocol.rs | 10 | ||||
-rw-r--r-- | src/server.rs | 70 |
4 files changed, 98 insertions, 80 deletions
@@ -1,11 +1,29 @@ -{ pkgs ? import (import ./nix/sources.nix).nixpkgs { } }: +{ pkgs ? import (import ./nix/sources.nix).nixpkgs { + overlays = [ + (self: super: { + "format" = pkgs.writers.writeDashBin "format" '' + set -efu + cd ${self.lib.escapeShellArg (toString ./.)} + find src -iname '*.rs' -exec ${pkgs.rustfmt}/bin/rustfmt '{}' \; + ''; + "watch" = pkgs.writers.writeDashBin "watch" '' + set -efu + cd ${self.lib.escapeShellArg (toString ./.)} + find src -iname '*.rs' | entr -rs 'clear; cargo check' + ''; + }) + ]; + } +}: let inherit (pkgs) lib; in pkgs.mkShell rec { nativeBuildInputs = [ pkgs.cargo + pkgs.format pkgs.pkg-config pkgs.rustc pkgs.rustfmt + pkgs.watch ]; buildInputs = [ pkgs.alsa-lib diff --git a/src/client.rs b/src/client.rs index 007edc6..d111732 100644 --- a/src/client.rs +++ b/src/client.rs @@ -21,8 +21,6 @@ use bevy::prelude::*; use bevy::sprite::{MaterialMesh2dBundle, Mesh2dHandle}; use lightyear::client::connection::ConnectionManager; use lightyear::client::events::*; -use lightyear::client::input::InputManager; -use lightyear::client::input::InputSystemSet; use lightyear::prelude::client::ClientConnection; use lightyear::prelude::client::NetClient; use lightyear::prelude::*; @@ -128,12 +126,7 @@ impl Plugin for ClientPlugin { move_camera.after(control_camera).after(lock_camera), ), ) - .add_systems( - FixedPreUpdate, - buffer_input - .in_set(InputSystemSet::BufferInputs) - .before(choose_attack), - ) + .add_systems(PreUpdate, player_input.before(choose_attack)) .add_systems(Last, (gizmos_hover_indicator, gizmos_attack_indicator)); } } @@ -224,10 +217,10 @@ fn setup( }); client.connect().unwrap(); connection_manager - .send_message::<Channel1, SelectChampion>(SelectChampion(champion.0)) + .send_message::<Input, SelectChampion>(SelectChampion(champion.0)) .unwrap(); connection_manager - .send_message::<Channel1, SelectFaction>(SelectFaction(faction.0)) + .send_message::<Input, SelectFaction>(SelectFaction(faction.0)) .unwrap(); } @@ -316,17 +309,16 @@ fn move_players(mut players: Query<(&mut Transform, &PlayerPosition), Changed<Pl } } -fn buffer_input( +fn player_input( players: Query<(&PlayerId, &PlayerPosition, &Shape)>, mut attack: ResMut<Attack>, cameras: Query<(&Camera, &GlobalTransform)>, client_id: Res<MyClientId>, keyboard_input: Res<ButtonInput<KeyCode>>, mouse_input: Res<ButtonInput<MouseButton>>, - mut input_manager: ResMut<InputManager<Inputs>>, + mut connection_manager: ResMut<ConnectionManager<MyProtocol>>, windows: Query<&Window>, champion: Res<MyChampion>, - tick_manager: Res<TickManager>, ) { if mouse_input.just_pressed(MouseButton::Left) { match attack.0 { @@ -340,10 +332,12 @@ fn buffer_input( return; }; let direction = world_position - position.0; - input_manager.add_input( - Inputs::Imperative(Imperative::AttackDirection(ability_slot, direction)), - tick_manager.tick(), - ); + connection_manager + .send_message::<Input, Imperative>(Imperative::AttackDirection( + ability_slot, + direction, + )) + .unwrap(); attack.0 = None; } Ability::Targeted(_) => { @@ -356,10 +350,12 @@ fn buffer_input( ) else { return; }; - input_manager.add_input( - Inputs::Imperative(Imperative::AttackTarget(ability_slot, target_player)), - tick_manager.tick(), - ); + connection_manager + .send_message::<Input, Imperative>(Imperative::AttackTarget( + ability_slot, + target_player, + )) + .unwrap(); attack.0 = None; } }, @@ -371,16 +367,17 @@ fn buffer_input( &players, &windows, ) { - input_manager.add_input( - Inputs::Imperative(Imperative::AttackTarget(AbilitySlot::A, target_player)), - tick_manager.tick(), - ); + connection_manager + .send_message::<Input, Imperative>(Imperative::AttackTarget( + AbilitySlot::A, + target_player, + )) + .unwrap(); } else { if let Some(world_position) = cursor_world_position(&windows, &cameras) { - input_manager.add_input( - Inputs::Imperative(Imperative::WalkTo(world_position)), - tick_manager.tick(), - ); + connection_manager + .send_message::<Input, Imperative>(Imperative::WalkTo(world_position)) + .unwrap(); } } } @@ -389,18 +386,17 @@ fn buffer_input( match attack.0 { None => { if let Some(world_position) = cursor_world_position(&windows, &cameras) { - input_manager.add_input( - Inputs::Imperative(Imperative::WalkTo(world_position)), - tick_manager.tick(), - ); + connection_manager + .send_message::<Input, Imperative>(Imperative::WalkTo(world_position)) + .unwrap(); } } Some(_) => {} } } else if keyboard_input.just_pressed(KeyCode::KeyS) { - input_manager.add_input(Inputs::Imperative(Imperative::Idle), tick_manager.tick()); - } else { - input_manager.add_input(Inputs::None, tick_manager.tick()); + connection_manager + .send_message::<Input, Imperative>(Imperative::Idle) + .unwrap(); } } @@ -409,8 +405,7 @@ fn choose_attack( keyboard_input: Res<ButtonInput<KeyCode>>, mouse_input: Res<ButtonInput<MouseButton>>, mut attack: ResMut<Attack>, - mut input_manager: ResMut<InputManager<Inputs>>, - tick_manager: Res<TickManager>, + mut connection_manager: ResMut<ConnectionManager<MyProtocol>>, ) { if keyboard_input.just_pressed(KeyCode::KeyA) { attack.0 = Some(AbilitySlot::A); @@ -436,10 +431,9 @@ fn choose_attack( match attack.0 { Some(ability_slot) => match champion.0.ability(ability_slot) { Ability::Activated(_) => { - input_manager.add_input( - Inputs::Activation(Activation::Activate(ability_slot)), - tick_manager.tick(), - ); + connection_manager + .send_message::<Input, Activation>(Activation::Activate(ability_slot)) + .unwrap(); attack.0 = None; } _ => {} diff --git a/src/protocol.rs b/src/protocol.rs index f4c77bb..f75cfab 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -19,8 +19,6 @@ use serde::Serialize; #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub enum Inputs { - Imperative(Imperative), - Activation(Activation), None, } impl UserAction for Inputs {} @@ -39,6 +37,8 @@ pub enum Messages { SelectChampion(SelectChampion), SelectFaction(SelectFaction), HealthChanged(HealthChanged), + Imperative(Imperative), + Activation(Activation), } #[component_protocol(protocol = "MyProtocol")] @@ -60,7 +60,7 @@ pub enum Components { } #[derive(Channel)] -pub struct Channel1; +pub struct Input; protocolize! { Self = MyProtocol, @@ -71,8 +71,8 @@ protocolize! { pub fn protocol() -> MyProtocol { let mut protocol = MyProtocol::default(); - protocol.add_channel::<Channel1>(ChannelSettings { - mode: ChannelMode::UnorderedReliable(Default::default()), + protocol.add_channel::<Input>(ChannelSettings { + mode: ChannelMode::OrderedReliable(Default::default()), ..Default::default() }); protocol diff --git a/src/server.rs b/src/server.rs index a509f28..b6c23c6 100644 --- a/src/server.rs +++ b/src/server.rs @@ -68,6 +68,10 @@ impl Plugin for ServerPlugin { receive_message_select_faction, ), ) + .add_systems( + Update, + (receive_message_imperative, receive_message_activation), + ) .add_systems(FixedUpdate, timers_tick) .add_systems(FixedUpdate, effective_stats.after(buffs_despawn)) .add_systems(FixedUpdate, health_regen.after(timers_tick)) @@ -80,7 +84,8 @@ impl Plugin for ServerPlugin { activation.after(cooldown_decrement), imperative_walk_to, ) - .after(player_input), + .after(receive_message_activation) + .after(receive_message_imperative), ) .add_systems( FixedUpdate, @@ -101,7 +106,6 @@ impl Plugin for ServerPlugin { ) .add_systems(FixedUpdate, cooldown_decrement) .add_systems(FixedUpdate, (buffs_despawn, buffs_tick).chain()) - .add_systems(FixedUpdate, player_input) .add_systems( FixedUpdate, (tower_ai, (minion_ai_attack, minion_ai_walk).chain()) @@ -210,6 +214,36 @@ fn receive_message_select_faction( } } +fn receive_message_imperative( + entity_map: Res<EntityMap>, + mut commands: Commands, + mut reader: EventReader<MessageEvent<Imperative>>, +) { + for event in reader.read() { + let client_id = event.context(); + let imperative = event.message(); + let Some(entity) = entity_map.0.get(client_id) else { + continue; + }; + commands.entity(*entity).insert(*imperative); + } +} + +fn receive_message_activation( + entity_map: Res<EntityMap>, + mut commands: Commands, + mut reader: EventReader<MessageEvent<Activation>>, +) { + for event in reader.read() { + let client_id = event.context(); + let activation = event.message(); + let Some(entity) = entity_map.0.get(client_id) else { + continue; + }; + commands.entity(*entity).insert(*activation); + } +} + fn disconnects( mut commands: Commands, mut disconnects: EventReader<server::DisconnectEvent>, @@ -223,34 +257,6 @@ fn disconnects( } } -fn player_input( - entity_map: Res<EntityMap>, - mut input_reader: EventReader<server::InputEvent<Inputs>>, - mut imperatives: Query<&mut Imperative>, - mut activations: Query<&mut Activation>, -) { - for input in input_reader.read() { - let client_id = input.context(); - if let Some(input) = input.input() { - if let Some(entity_id) = entity_map.0.get(client_id) { - match input { - Inputs::Imperative(new_imperative) => { - if let Ok(mut imperative) = imperatives.get_mut(*entity_id) { - *imperative = *new_imperative; - } - } - Inputs::Activation(new_activation) => { - if let Ok(mut activation) = activations.get_mut(*entity_id) { - *activation = *new_activation; - } - } - Inputs::None => {} - } - } - } - } -} - fn imperative_walk_to( mut players: Query<(Entity, &mut Imperative, &EffectiveStats)>, mut positions: Query<&mut PlayerPosition>, @@ -615,7 +621,7 @@ fn projectile_despawn( }; let applied_damage = damage.apply(hit_effective_stats.0); hit_health.apply_damage(applied_damage); - let _ = connection_manager.send_message_to_target::<Channel1, HealthChanged>( + let _ = connection_manager.send_message_to_target::<Input, HealthChanged>( HealthChanged(HealthEvent { target_player: *hit_player_id, health_gained: -applied_damage, @@ -647,7 +653,7 @@ fn health_regen( if health_regen_timer.0.just_finished() { for (target_player, mut health, effective_stats) in healths.iter_mut() { health.heal(HEALTH_REGEN, effective_stats.0.max_health); - let _ = connection_manager.send_message_to_target::<Channel1, HealthChanged>( + let _ = connection_manager.send_message_to_target::<Input, HealthChanged>( HealthChanged(HealthEvent { target_player: *target_player, health_gained: HEALTH_REGEN, |