diff --git a/azalea-client/src/plugins/attack.rs b/azalea-client/src/plugins/attack.rs index 5ba84772..34122108 100644 --- a/azalea-client/src/plugins/attack.rs +++ b/azalea-client/src/plugins/attack.rs @@ -33,6 +33,7 @@ impl Plugin for AttackPlugin { ( increment_ticks_since_last_attack, update_attack_strength_scale.after(PhysicsSet), + handle_attack_queued.before(super::tick_end::game_tick_packet), ) .chain(), ); @@ -61,38 +62,45 @@ impl Client { } } -#[derive(Event)] -pub struct AttackEvent { - pub entity: Entity, +/// A component that indicates that this client will be attacking the given +/// entity next tick. +#[derive(Component, Clone, Debug)] +struct AttackQueued { pub target: MinecraftEntityId, } -pub fn handle_attack_event( - mut events: EventReader, +fn handle_attack_queued( + mut commands: Commands, mut query: Query<( + Entity, + &AttackQueued, &LocalGameMode, &mut TicksSinceLastAttack, &mut Physics, &mut Sprinting, - &mut ShiftKeyDown, + &ShiftKeyDown, )>, - mut commands: Commands, - mut swing_arm_event: EventWriter, ) { - for event in events.read() { - let (game_mode, mut ticks_since_last_attack, mut physics, mut sprinting, sneaking) = - query.get_mut(event.entity).unwrap(); + for ( + entity, + attack_queued, + game_mode, + mut ticks_since_last_attack, + mut physics, + mut sprinting, + sneaking, + ) in &mut query + { + commands.entity(entity).remove::(); - swing_arm_event.send(SwingArmEvent { - entity: event.entity, - }); commands.trigger(SendPacketEvent::new( - event.entity, + entity, ServerboundInteract { - entity_id: event.target, + entity_id: attack_queued.target, action: s_interact::ActionType::Attack, using_secondary_action: **sneaking, }, )); + commands.trigger(SwingArmEvent { entity }); // we can't attack if we're in spectator mode but it still sends the attack // packet @@ -107,6 +115,22 @@ pub fn handle_attack_event( } } +/// Queues up an attack packet for next tick by inserting the [`AttackQueued`] +/// component to our client. +#[derive(Event)] +pub struct AttackEvent { + /// Our client entity that will send the packets to attack. + pub entity: Entity, + pub target: MinecraftEntityId, +} +pub fn handle_attack_event(mut events: EventReader, mut commands: Commands) { + for event in events.read() { + commands.entity(event.entity).insert(AttackQueued { + target: event.target, + }); + } +} + #[derive(Default, Bundle)] pub struct AttackBundle { pub ticks_since_last_attack: TicksSinceLastAttack, diff --git a/azalea-client/src/plugins/interact.rs b/azalea-client/src/plugins/interact.rs index f9513183..f7239c17 100644 --- a/azalea-client/src/plugins/interact.rs +++ b/azalea-client/src/plugins/interact.rs @@ -23,6 +23,7 @@ use bevy_ecs::{ component::Component, entity::Entity, event::{Event, EventReader}, + observer::Trigger, query::{Changed, With}, schedule::IntoSystemConfigs, system::{Commands, Query, Res}, @@ -64,7 +65,8 @@ impl Plugin for InteractPlugin { .after(InventorySet) .after(MoveEventsSet), ), - ); + ) + .add_observer(handle_swing_arm_trigger); } } @@ -295,18 +297,21 @@ pub fn can_use_game_master_blocks( /// Swing your arm. This is purely a visual effect and won't interact with /// anything in the world. -#[derive(Event)] +#[derive(Event, Clone, Debug)] pub struct SwingArmEvent { pub entity: Entity, } +pub fn handle_swing_arm_trigger(trigger: Trigger, mut commands: Commands) { + commands.trigger(SendPacketEvent::new( + trigger.event().entity, + ServerboundSwing { + hand: InteractionHand::MainHand, + }, + )); +} pub fn handle_swing_arm_event(mut events: EventReader, mut commands: Commands) { for event in events.read() { - commands.trigger(SendPacketEvent::new( - event.entity, - ServerboundSwing { - hand: InteractionHand::MainHand, - }, - )); + commands.trigger(event.clone()); } }