aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/plugins
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2025-05-06 14:20:57 -1300
committermat <git@matdoes.dev>2025-05-06 14:20:57 -1300
commite9452032bfc95cb7ad4a8798b13648e164536cf1 (patch)
treed62694761560085d979886d0822b8dfd942d3db2 /azalea-client/src/plugins
parentd58a1c4fa0bd0c695e670ec52874f11cce64cd01 (diff)
downloadazalea-drasl-e9452032bfc95cb7ad4a8798b13648e164536cf1.tar.xz
fix various issues with mining
Diffstat (limited to 'azalea-client/src/plugins')
-rw-r--r--azalea-client/src/plugins/interact.rs1
-rw-r--r--azalea-client/src/plugins/mining.rs160
-rw-r--r--azalea-client/src/plugins/packet/game/events.rs3
3 files changed, 89 insertions, 75 deletions
diff --git a/azalea-client/src/plugins/interact.rs b/azalea-client/src/plugins/interact.rs
index 9ca216fb..81c69121 100644
--- a/azalea-client/src/plugins/interact.rs
+++ b/azalea-client/src/plugins/interact.rs
@@ -98,6 +98,7 @@ impl AddAssign<u32> for CurrentSequenceNumber {
}
/// A component that contains the block that the player is currently looking at.
+#[doc(alias("looking at", "looking at block", "crosshair"))]
#[derive(Component, Clone, Debug, Deref, DerefMut)]
pub struct HitResultComponent(BlockHitResult);
diff --git a/azalea-client/src/plugins/mining.rs b/azalea-client/src/plugins/mining.rs
index f4caec41..f2fb3361 100644
--- a/azalea-client/src/plugins/mining.rs
+++ b/azalea-client/src/plugins/mining.rs
@@ -2,7 +2,7 @@ use azalea_block::{Block, BlockState, fluid_state::FluidState};
use azalea_core::{direction::Direction, game_type::GameMode, position::BlockPos, tick::GameTick};
use azalea_entity::{FluidOnEyes, Physics, mining::get_mine_progress};
use azalea_inventory::ItemStack;
-use azalea_physics::PhysicsSet;
+use azalea_physics::{PhysicsSet, collision::BlockWithShape};
use azalea_protocol::packets::game::s_player_action::{self, ServerboundPlayerAction};
use azalea_world::{InstanceContainer, InstanceName};
use bevy_app::{App, Plugin, Update};
@@ -10,7 +10,7 @@ use bevy_ecs::prelude::*;
use derive_more::{Deref, DerefMut};
use crate::{
- Client,
+ Client, InstanceHolder,
interact::{
CurrentSequenceNumber, HitResultComponent, SwingArmEvent, can_use_game_master_blocks,
check_is_interaction_restricted,
@@ -26,14 +26,18 @@ pub struct MiningPlugin;
impl Plugin for MiningPlugin {
fn build(&self, app: &mut App) {
app.add_event::<StartMiningBlockEvent>()
- .add_event::<StartMiningBlockWithDirectionEvent>()
.add_event::<FinishMiningBlockEvent>()
.add_event::<StopMiningBlockEvent>()
.add_event::<MineBlockProgressEvent>()
.add_event::<AttackBlockEvent>()
.add_systems(
GameTick,
- (continue_mining_block, handle_auto_mine)
+ (
+ update_mining_component,
+ continue_mining_block,
+ handle_auto_mine,
+ handle_mining_queued,
+ )
.chain()
.before(PhysicsSet),
)
@@ -41,7 +45,6 @@ impl Plugin for MiningPlugin {
Update,
(
handle_start_mining_block_event,
- handle_start_mining_block_with_direction_event,
handle_finish_mining_block_event,
handle_stop_mining_block_event,
)
@@ -65,7 +68,9 @@ pub struct MiningSet;
impl Client {
pub fn start_mining(&self, position: BlockPos) {
- self.ecs.lock().send_event(StartMiningBlockEvent {
+ let mut ecs = self.ecs.lock();
+
+ ecs.send_event(StartMiningBlockEvent {
entity: self.entity,
position,
});
@@ -155,8 +160,8 @@ pub struct StartMiningBlockEvent {
pub position: BlockPos,
}
fn handle_start_mining_block_event(
+ mut commands: Commands,
mut events: EventReader<StartMiningBlockEvent>,
- mut start_mining_events: EventWriter<StartMiningBlockWithDirectionEvent>,
mut query: Query<&HitResultComponent>,
) {
for event in events.read() {
@@ -168,29 +173,29 @@ fn handle_start_mining_block_event(
// we're not looking at the block, arbitrary direction
Direction::Down
};
- start_mining_events.write(StartMiningBlockWithDirectionEvent {
- entity: event.entity,
+ commands.entity(event.entity).insert(MiningQueued {
position: event.position,
direction,
});
}
}
-#[derive(Event)]
-pub struct StartMiningBlockWithDirectionEvent {
- pub entity: Entity,
+/// Present on entities when they're going to start mining a block next tick.
+#[derive(Component)]
+pub struct MiningQueued {
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<StartMiningBlockWithDirectionEvent>,
- mut finish_mining_events: EventWriter<FinishMiningBlockEvent>,
+fn handle_mining_queued(
mut commands: Commands,
+ mut finish_mining_events: EventWriter<FinishMiningBlockEvent>,
mut attack_block_events: EventWriter<AttackBlockEvent>,
mut mine_block_progress_events: EventWriter<MineBlockProgressEvent>,
- mut query: Query<(
- &InstanceName,
+ query: Query<(
+ Entity,
+ &MiningQueued,
+ &InstanceHolder,
&LocalGameMode,
&Inventory,
&FluidOnEyes,
@@ -203,29 +208,30 @@ fn handle_start_mining_block_with_direction_event(
&mut MineItem,
&mut MineBlockPos,
)>,
- instances: Res<InstanceContainer>,
) {
- for event in events.read() {
- let (
- instance_name,
- game_mode,
- inventory,
- fluid_on_eyes,
- physics,
- mining,
- mut sequence_number,
- mut mine_delay,
- mut mine_progress,
- mut mine_ticks,
- mut current_mining_item,
- mut current_mining_pos,
- ) = query.get_mut(event.entity).unwrap();
+ for (
+ entity,
+ mining_queued,
+ instance_holder,
+ game_mode,
+ inventory,
+ fluid_on_eyes,
+ physics,
+ mining,
+ mut sequence_number,
+ mut mine_delay,
+ mut mine_progress,
+ mut mine_ticks,
+ mut current_mining_item,
+ mut current_mining_pos,
+ ) in query
+ {
+ commands.entity(entity).remove::<MiningQueued>();
- let instance_lock = instances.get(instance_name).unwrap();
- let instance = instance_lock.read();
+ let instance = instance_holder.instance.read();
if check_is_interaction_restricted(
&instance,
- &event.position,
+ &mining_queued.position,
&game_mode.current,
inventory,
) {
@@ -237,13 +243,13 @@ fn handle_start_mining_block_with_direction_event(
if game_mode.current == GameMode::Creative {
*sequence_number += 1;
finish_mining_events.write(FinishMiningBlockEvent {
- entity: event.entity,
- position: event.position,
+ entity,
+ position: mining_queued.position,
});
**mine_delay = 5;
} else if mining.is_none()
|| !is_same_mining_target(
- event.position,
+ mining_queued.position,
inventory,
&current_mining_pos,
&current_mining_item,
@@ -252,40 +258,29 @@ fn handle_start_mining_block_with_direction_event(
if mining.is_some() {
// send a packet to stop mining since we just changed target
commands.trigger(SendPacketEvent::new(
- event.entity,
+ entity,
ServerboundPlayerAction {
action: s_player_action::Action::AbortDestroyBlock,
pos: current_mining_pos
.expect("IsMining is true so MineBlockPos must be present"),
- direction: event.direction,
+ direction: mining_queued.direction,
sequence: 0,
},
));
}
let target_block_state = instance
- .get_block_state(&event.position)
+ .get_block_state(&mining_queued.position)
.unwrap_or_default();
- *sequence_number += 1;
- let target_registry_block = azalea_registry::Block::from(target_block_state);
// we can't break blocks if they don't have a bounding box
-
- // TODO: So right now azalea doesn't differenciate between different types of
- // bounding boxes. See ClipContext::block_shape for more info. Ideally this
- // should just call ClipContext::block_shape and check if it's empty.
- let block_is_solid = !target_block_state.is_air()
- // this is a hack to make sure we can't break water or lava
- && !matches!(
- target_registry_block,
- azalea_registry::Block::Water | azalea_registry::Block::Lava
- );
+ let block_is_solid = !target_block_state.outline_shape().is_empty();
if block_is_solid && **mine_progress == 0. {
// interact with the block (like note block left click) here
attack_block_events.write(AttackBlockEvent {
- entity: event.entity,
- position: event.position,
+ entity,
+ position: mining_queued.position,
});
}
@@ -304,34 +299,37 @@ fn handle_start_mining_block_with_direction_event(
{
// block was broken instantly
finish_mining_events.write(FinishMiningBlockEvent {
- entity: event.entity,
- position: event.position,
+ entity,
+ position: mining_queued.position,
});
} else {
- commands.entity(event.entity).insert(Mining {
- pos: event.position,
- dir: event.direction,
+ commands.entity(entity).insert(Mining {
+ pos: mining_queued.position,
+ dir: mining_queued.direction,
});
- **current_mining_pos = Some(event.position);
+ **current_mining_pos = Some(mining_queued.position);
**current_mining_item = held_item;
**mine_progress = 0.;
**mine_ticks = 0.;
mine_block_progress_events.write(MineBlockProgressEvent {
- entity: event.entity,
- position: event.position,
+ entity,
+ position: mining_queued.position,
destroy_stage: mine_progress.destroy_stage(),
});
}
+ *sequence_number += 1;
commands.trigger(SendPacketEvent::new(
- event.entity,
+ entity,
ServerboundPlayerAction {
action: s_player_action::Action::StartDestroyBlock,
- pos: event.position,
- direction: event.direction,
+ pos: mining_queued.position,
+ direction: mining_queued.direction,
sequence: **sequence_number,
},
));
+ commands.trigger(SwingArmEvent { entity });
+ commands.trigger(SwingArmEvent { entity });
}
}
}
@@ -530,8 +528,6 @@ pub fn continue_mining_block(
mut commands: Commands,
mut mine_block_progress_events: EventWriter<MineBlockProgressEvent>,
mut finish_mining_events: EventWriter<FinishMiningBlockEvent>,
- mut start_mining_events: EventWriter<StartMiningBlockWithDirectionEvent>,
- mut swing_arm_events: EventWriter<SwingArmEvent>,
instances: Res<InstanceContainer>,
) {
for (
@@ -572,17 +568,20 @@ pub fn continue_mining_block(
sequence: **sequence_number,
},
));
- swing_arm_events.write(SwingArmEvent { entity });
+ commands.trigger(SwingArmEvent { entity });
} else if is_same_mining_target(
mining.pos,
inventory,
current_mining_pos,
current_mining_item,
) {
+ println!("continue mining block at {:?}", mining.pos);
let instance_lock = instances.get(instance_name).unwrap();
let instance = instance_lock.read();
let target_block_state = instance.get_block_state(&mining.pos).unwrap_or_default();
+ println!("target_block_state: {:?}", target_block_state);
+
if target_block_state.is_air() {
commands.entity(entity).remove::<Mining>();
continue;
@@ -604,6 +603,7 @@ pub fn continue_mining_block(
if **mine_progress >= 1. {
commands.entity(entity).remove::<Mining>();
*sequence_number += 1;
+ println!("finished mining block at {:?}", mining.pos);
finish_mining_events.write(FinishMiningBlockEvent {
entity,
position: mining.pos,
@@ -627,15 +627,27 @@ pub fn continue_mining_block(
position: mining.pos,
destroy_stage: mine_progress.destroy_stage(),
});
- swing_arm_events.write(SwingArmEvent { entity });
+ commands.trigger(SwingArmEvent { entity });
} else {
- start_mining_events.write(StartMiningBlockWithDirectionEvent {
- entity,
+ println!("switching mining target to {:?}", mining.pos);
+ commands.entity(entity).insert(MiningQueued {
position: mining.pos,
direction: mining.dir,
});
}
+ }
+}
- swing_arm_events.write(SwingArmEvent { entity });
+fn update_mining_component(
+ mut commands: Commands,
+ mut query: Query<(Entity, &mut Mining, &HitResultComponent)>,
+) {
+ for (entity, mut mining, hit_result_component) in &mut query.iter_mut() {
+ if hit_result_component.miss {
+ commands.entity(entity).remove::<Mining>();
+ } else {
+ mining.pos = hit_result_component.block_pos;
+ mining.dir = hit_result_component.direction;
+ }
}
}
diff --git a/azalea-client/src/plugins/packet/game/events.rs b/azalea-client/src/plugins/packet/game/events.rs
index 68bfb4b3..707d2cd9 100644
--- a/azalea-client/src/plugins/packet/game/events.rs
+++ b/azalea-client/src/plugins/packet/game/events.rs
@@ -9,7 +9,7 @@ use azalea_protocol::packets::{
use azalea_world::Instance;
use bevy_ecs::prelude::*;
use parking_lot::RwLock;
-use tracing::error;
+use tracing::{error, trace};
use uuid::Uuid;
use crate::{PlayerInfo, client::InGameState, connection::RawConnection};
@@ -60,6 +60,7 @@ pub fn handle_outgoing_packets_observer(
mut query: Query<(&mut RawConnection, Option<&InGameState>)>,
) {
let event = trigger.event();
+ trace!("Sending game packet: {:?}", event.packet);
if let Ok((mut raw_connection, in_game_state)) = query.get_mut(event.sent_by) {
if in_game_state.is_none() {