diff --git a/azalea-client/src/mining.rs b/azalea-client/src/mining.rs index f0b86db19..6e4b58f37 100644 --- a/azalea-client/src/mining.rs +++ b/azalea-client/src/mining.rs @@ -1,6 +1,6 @@ use azalea_block::{Block, BlockState, FluidState}; use azalea_core::{direction::Direction, game_type::GameMode, position::BlockPos, tick::GameTick}; -use azalea_entity::{mining::get_mine_progress, FluidOnEyes, Physics}; +use azalea_entity::{mining::get_mine_progress, FluidOnEyes, Physics, LocalEntity}; use azalea_inventory::ItemSlot; use azalea_physics::PhysicsSet; use azalea_protocol::packets::game::serverbound_player_action_packet::{ @@ -10,6 +10,7 @@ use azalea_world::{InstanceContainer, InstanceName}; use bevy_app::{App, Plugin, Update}; use bevy_ecs::prelude::*; use derive_more::{Deref, DerefMut}; +use azalea_entity::metadata::Player; use crate::{ interact::{ @@ -25,6 +26,7 @@ use crate::{ /// A plugin that allows clients to break blocks in the world. pub struct MinePlugin; + impl Plugin for MinePlugin { fn build(&self, app: &mut App) { app.add_event::() @@ -33,7 +35,15 @@ impl Plugin for MinePlugin { .add_event::() .add_event::() .add_event::() - .add_systems(GameTick, continue_mining_block.before(PhysicsSet)) + .add_systems( + GameTick, + ( + continue_mining_block, + handle_left_click_mine + ) + .chain() + .before(PhysicsSet), + ) .add_systems( Update, ( @@ -66,6 +76,69 @@ impl Client { position, }); } + + /// When enabled, the bot will mine any block that it is looking at if it is reachable. + pub fn left_click_mine(&self, enabled: bool) { + let mut ecs = self.ecs.lock(); + let mut entity_mut = ecs.entity_mut(self.entity); + + if enabled { + entity_mut.insert(LeftClickMine); + } else { + entity_mut.remove::(); + } + } +} + +#[derive(Component)] +pub struct LeftClickMine; + +#[allow(clippy::type_complexity)] +fn handle_left_click_mine( + mut query: Query< + ( + &HitResultComponent, + Entity, + Option<&Mining>, + &InventoryComponent, + &MineBlockPos, + &MineItem, + ), + (With, With, With), + >, + mut start_mining_block_event: EventWriter, + mut stop_mining_block_event: EventWriter +) { + for ( + hit_result_component, + entity, + mining, + inventory, + current_mining_pos, + current_mining_item, + ) in &mut query.iter_mut() + { + let block_pos = hit_result_component.block_pos; + + if (mining.is_none() + || !is_same_mining_target( + block_pos, + inventory, + current_mining_pos, + current_mining_item, + )) && !hit_result_component.miss + { + start_mining_block_event.send(StartMiningBlockEvent { + entity, + position: block_pos, + }); + } else if mining.is_some() && hit_result_component.miss { + // Stop mining as the block is not reachable + stop_mining_block_event.send(StopMiningBlockEvent { + entity + }); + } + } } /// Information about the block we're currently mining. This is only present if @@ -85,6 +158,7 @@ pub struct StartMiningBlockEvent { pub entity: Entity, pub position: BlockPos, } + fn handle_start_mining_block_event( mut events: EventReader, mut start_mining_events: EventWriter, @@ -113,6 +187,7 @@ pub struct StartMiningBlockWithDirectionEvent { pub position: BlockPos, pub direction: Direction, } + #[allow(clippy::too_many_arguments, clippy::type_complexity)] fn handle_start_mining_block_with_direction_event( mut events: EventReader, @@ -175,11 +250,11 @@ fn handle_start_mining_block_with_direction_event( **mine_delay = 5; } else if mining.is_none() || !is_same_mining_target( - event.position, - inventory, - ¤t_mining_pos, - ¤t_mining_item, - ) + event.position, + inventory, + ¤t_mining_pos, + ¤t_mining_item, + ) { if mining.is_some() { // send a packet to stop mining since we just changed target @@ -192,7 +267,7 @@ fn handle_start_mining_block_with_direction_event( direction: event.direction, sequence: 0, } - .get(), + .get(), }); } @@ -228,12 +303,12 @@ fn handle_start_mining_block_with_direction_event( if block_is_solid && get_mine_progress( - block.as_ref(), - held_item.kind(), - &inventory.inventory_menu, - fluid_on_eyes, - physics, - ) >= 1. + block.as_ref(), + held_item.kind(), + &inventory.inventory_menu, + fluid_on_eyes, + physics, + ) >= 1. { // block was broken instantly finish_mining_events.send(FinishMiningBlockEvent { @@ -264,7 +339,7 @@ fn handle_start_mining_block_with_direction_event( direction: event.direction, sequence: **sequence_number, } - .get(), + .get(), }); } } @@ -414,6 +489,7 @@ fn handle_finish_mining_block_event( pub struct StopMiningBlockEvent { pub entity: Entity, } + fn handle_stop_mining_block_event( mut events: EventReader, mut send_packet_events: EventWriter, @@ -434,7 +510,7 @@ fn handle_stop_mining_block_event( direction: Direction::Down, sequence: 0, } - .get(), + .get(), }); commands.entity(event.entity).remove::(); **mine_progress = 0.; @@ -508,7 +584,7 @@ fn continue_mining_block( direction: mining.dir, sequence: **sequence_number, } - .get(), + .get(), }); swing_arm_events.send(SwingArmEvent { entity }); } else if is_same_mining_target( @@ -554,7 +630,7 @@ fn continue_mining_block( direction: mining.dir, sequence: **sequence_number, } - .get(), + .get(), }); **mine_progress = 0.; **mine_ticks = 0.;