aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2025-12-28 09:06:47 -0330
committermat <git@matdoes.dev>2025-12-28 09:06:47 -0330
commit839d536e8020b291bc1d213a5e8e823dc513a940 (patch)
tree60cab8b908ad53af0126e2cb1dec670d073936a3
parent5b1a78baf757897532be8c308a37c99fb2ca3352 (diff)
downloadazalea-drasl-839d536e8020b291bc1d213a5e8e823dc513a940.tar.xz
add a few more functions for getting common components to Client
-rw-r--r--azalea/examples/steal.rs4
-rw-r--r--azalea/examples/testbot/commands/debug.rs8
-rw-r--r--azalea/examples/testbot/killaura.rs33
-rw-r--r--azalea/examples/todo/craft_dig_straight_down.rs5
-rw-r--r--azalea/src/client_impl/entity_query.rs31
-rw-r--r--azalea/src/client_impl/interact.rs10
-rw-r--r--azalea/src/client_impl/inventory.rs7
-rw-r--r--azalea/src/client_impl/mod.rs24
-rw-r--r--azalea/src/client_impl/movement.rs5
-rw-r--r--azalea/src/container.rs4
-rw-r--r--azalea/src/swarm/mod.rs2
11 files changed, 71 insertions, 62 deletions
diff --git a/azalea/examples/steal.rs b/azalea/examples/steal.rs
index 4e8c078c..b5a26423 100644
--- a/azalea/examples/steal.rs
+++ b/azalea/examples/steal.rs
@@ -3,7 +3,7 @@
use std::sync::Arc;
use azalea::{BlockPos, pathfinder::goals::RadiusGoal, prelude::*};
-use azalea_inventory::{ItemStack, operations::QuickMoveClick};
+use azalea_inventory::ItemStack;
use azalea_registry::builtin::{BlockKind, ItemKind};
use parking_lot::Mutex;
@@ -81,7 +81,7 @@ async fn steal(bot: Client, state: State) -> anyhow::Result<()> {
};
if item.kind == ItemKind::Diamond {
println!("clicking slot ^");
- chest.click(QuickMoveClick::Left { slot: index as u16 });
+ chest.left_click(index);
}
}
}
diff --git a/azalea/examples/testbot/commands/debug.rs b/azalea/examples/testbot/commands/debug.rs
index 711c3260..d75b4c0a 100644
--- a/azalea/examples/testbot/commands/debug.rs
+++ b/azalea/examples/testbot/commands/debug.rs
@@ -88,7 +88,7 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
commands.register(literal("getdirection").executes(|ctx: &Ctx| {
let source = ctx.source.lock();
- let direction = source.bot.component::<LookDirection>();
+ let direction = source.bot.direction();
source.reply(format!(
"I'm looking at {}, {}",
direction.y_rot(),
@@ -108,9 +108,9 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
commands.register(literal("lookingat").executes(|ctx: &Ctx| {
let source = ctx.source.lock();
- let hit_result = source.bot.component::<HitResultComponent>();
+ let hit_result = source.bot.hit_result();
- match &**hit_result {
+ match &hit_result {
HitResult::Block(r) => {
if r.miss {
source.reply("I'm not looking at anything");
@@ -242,7 +242,7 @@ pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
commands.register(literal("attributes").executes(|ctx: &Ctx| {
let source = ctx.source.lock();
- let attributes = source.bot.component::<Attributes>();
+ let attributes = source.bot.attributes();
println!("attributes: {attributes:?}");
1
}));
diff --git a/azalea/examples/testbot/killaura.rs b/azalea/examples/testbot/killaura.rs
index e3d9091c..e6eb40ba 100644
--- a/azalea/examples/testbot/killaura.rs
+++ b/azalea/examples/testbot/killaura.rs
@@ -2,7 +2,6 @@ use azalea::{
ecs::prelude::*,
entity::{Dead, LocalEntity, Position, metadata::AbstractMonster},
prelude::*,
- world::InstanceName,
};
use crate::State;
@@ -14,33 +13,19 @@ pub fn tick(bot: Client, state: State) -> anyhow::Result<()> {
if bot.has_attack_cooldown() {
return Ok(());
}
- let mut nearest_entity = None;
- let mut nearest_distance = f64::INFINITY;
let bot_position = bot.eye_position();
- let bot_instance_name = bot.component::<InstanceName>().clone();
- {
- let mut ecs = bot.ecs.write();
- let mut query = ecs
- .query_filtered::<(Entity, &Position, &InstanceName), (
- With<AbstractMonster>,
- Without<LocalEntity>,
- Without<Dead>,
- )>();
- for (entity_id, position, instance_name) in query.iter(&ecs) {
- if instance_name != &bot_instance_name {
- continue;
- }
- let distance = bot_position.distance_to(**position);
- if distance < 4. && distance < nearest_distance {
- nearest_entity = Some(entity_id);
- nearest_distance = distance;
- }
- }
- }
+ let nearest_entity = bot.nearest_entity_by::<&Position, (
+ With<AbstractMonster>,
+ Without<LocalEntity>,
+ Without<Dead>,
+ )>(|position: &Position| {
+ let distance = bot_position.distance_to(**position);
+ distance < 4.
+ });
+
if let Some(nearest_entity) = nearest_entity {
println!("attacking {nearest_entity:?}");
- println!("distance {nearest_distance:?}");
bot.attack(nearest_entity);
}
diff --git a/azalea/examples/todo/craft_dig_straight_down.rs b/azalea/examples/todo/craft_dig_straight_down.rs
index 153af299..d8254aa3 100644
--- a/azalea/examples/todo/craft_dig_straight_down.rs
+++ b/azalea/examples/todo/craft_dig_straight_down.rs
@@ -58,10 +58,7 @@ async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
bot.hold(&pickaxe);
loop {
- if let Err(e) = bot
- .dig(azalea::entity::feet_pos(bot.entity()).down(1))
- .await
- {
+ if let Err(e) = bot.dig(bot.entity().feet_pos().down(1)).await {
println!("{e:?}");
break;
}
diff --git a/azalea/src/client_impl/entity_query.rs b/azalea/src/client_impl/entity_query.rs
index ae623dc7..683d755e 100644
--- a/azalea/src/client_impl/entity_query.rs
+++ b/azalea/src/client_impl/entity_query.rs
@@ -21,8 +21,9 @@ impl Client {
///
/// This returns a reference to the component wrapped by a read guard. This
/// makes the component cheap to access, but means that the ECS cannot be
- /// mutated while it's in scope. In some cases, it may be simpler for you to
- /// immediately clone the component after accessing it.
+ /// mutated while it's in scope (it will cause a deadlock). In some cases,
+ /// it may be simpler for you to immediately clone the component after
+ /// accessing it.
///
/// If the component isn't guaranteed to be present, consider using
/// [`Self::get_component`] instead.
@@ -227,15 +228,19 @@ impl Client {
pub fn nearest_entities_by<Q: QueryData, F: QueryFilter>(
&self,
predicate: impl EntityPredicate<Q, F>,
- ) -> Vec<Entity> {
- let Some(instance_name) = self.get_component::<InstanceName>() else {
- return vec![];
- };
- let Some(position) = self.get_component::<Position>() else {
- return vec![];
+ ) -> Box<[Entity]> {
+ let (instance_name, position) = {
+ let Some(instance_name) = self.get_component::<InstanceName>() else {
+ return Box::new([]);
+ };
+ let Some(position) = self.get_component::<Position>() else {
+ return Box::new([]);
+ };
+
+ (instance_name.clone(), **position)
};
- let (instance_name, position) = (instance_name.clone(), *position);
- predicate.find_all_sorted(self.ecs.clone(), &instance_name, (&position).into())
+
+ predicate.find_all_sorted(self.ecs.clone(), &instance_name, position)
}
/// Get a component from an entity.
@@ -291,7 +296,7 @@ pub trait EntityPredicate<Q: QueryData, Filter: QueryFilter> {
ecs_lock: Arc<RwLock<World>>,
instance_name: &InstanceName,
nearest_to: Vec3,
- ) -> Vec<Entity>;
+ ) -> Box<[Entity]>;
}
impl<F, Q: QueryData, Filter: QueryFilter> EntityPredicate<Q, Filter> for F
where
@@ -316,7 +321,7 @@ where
ecs_lock: Arc<RwLock<World>>,
instance_name: &InstanceName,
nearest_to: Vec3,
- ) -> Vec<Entity> {
+ ) -> Box<[Entity]> {
let mut ecs = ecs_lock.write();
let mut query = ecs.query_filtered::<(Entity, &InstanceName, &Position, Q), Filter>();
let mut entities = query
@@ -333,6 +338,6 @@ where
entities
.into_iter()
.map(|(e, _)| e)
- .collect::<Vec<Entity>>()
+ .collect::<Box<[Entity]>>()
}
}
diff --git a/azalea/src/client_impl/interact.rs b/azalea/src/client_impl/interact.rs
index 8a9cf475..b3cda1e2 100644
--- a/azalea/src/client_impl/interact.rs
+++ b/azalea/src/client_impl/interact.rs
@@ -1,11 +1,17 @@
-use azalea_client::interact::{EntityInteractEvent, StartUseItemEvent};
-use azalea_core::position::BlockPos;
+use azalea_client::interact::{EntityInteractEvent, StartUseItemEvent, pick::HitResultComponent};
+use azalea_core::{hit_result::HitResult, position::BlockPos};
use azalea_protocol::packets::game::s_interact::InteractionHand;
use bevy_ecs::entity::Entity;
use crate::Client;
impl Client {
+ /// Returns the current [`HitResult`], which is the block or entity in the
+ /// client's crosshair.
+ pub fn hit_result(&self) -> HitResult {
+ (**self.component::<HitResultComponent>()).clone()
+ }
+
/// Right-click a block.
///
/// The behavior of this depends on the target block,
diff --git a/azalea/src/client_impl/inventory.rs b/azalea/src/client_impl/inventory.rs
index fc1e2e73..72a05136 100644
--- a/azalea/src/client_impl/inventory.rs
+++ b/azalea/src/client_impl/inventory.rs
@@ -7,8 +7,11 @@ use crate::Client;
impl Client {
/// Return the menu that is currently open, or the player's inventory if no
/// menu is open.
+ ///
+ /// If you need to interact with the menu, consider using
+ /// [`Self::open_inventory`] instead.
pub fn menu(&self) -> Menu {
- self.query_self::<&Inventory, _>(|inv| inv.menu().clone())
+ self.component::<Inventory>().menu().clone()
}
/// Returns the index of the hotbar slot that's currently selected.
@@ -19,7 +22,7 @@ impl Client {
///
/// You can use [`Self::set_selected_hotbar_slot`] to change it.
pub fn selected_hotbar_slot(&self) -> u8 {
- self.query_self::<&Inventory, _>(|inv| inv.selected_hotbar_slot)
+ self.component::<Inventory>().selected_hotbar_slot
}
/// Update the selected hotbar slot index.
diff --git a/azalea/src/client_impl/mod.rs b/azalea/src/client_impl/mod.rs
index bbbe23e0..419fc27e 100644
--- a/azalea/src/client_impl/mod.rs
+++ b/azalea/src/client_impl/mod.rs
@@ -35,7 +35,7 @@ use bevy_ecs::{
resource::Resource,
world::{Mut, World},
};
-use parking_lot::{MappedRwLockReadGuard, RwLock};
+use parking_lot::RwLock;
use tokio::sync::mpsc;
use uuid::Uuid;
@@ -308,9 +308,7 @@ impl Client {
// the login packet tells us the world name
self.query_self::<Option<&InstanceName>, _>(|ins| ins.is_some())
}
-}
-impl Client {
/// Get the position of this client.
///
/// This is a shortcut for `Vec3::from(&bot.component::<Position>())`.
@@ -395,10 +393,26 @@ impl Client {
(**self.component::<GameProfileComponent>()).clone()
}
+ /// Returns the [`Account`] for our client.
+ pub fn account(&self) -> Account {
+ self.component::<Account>().clone()
+ }
+
/// Returns the attribute values of our player, which can be used to
/// determine things like our movement speed.
- pub fn attributes(&self) -> MappedRwLockReadGuard<'_, Attributes> {
- self.component::<Attributes>()
+ pub fn attributes(&self) -> Attributes {
+ // this *could* return a mapped read guard for performance but that rarely
+ // matters and it's just easier for the user if it doesn't.
+ self.component::<Attributes>().clone()
+ }
+
+ /// Get the name of the instance (world) that the bot is in.
+ ///
+ /// This can be used to check if the client is in the same world as another
+ /// entity.
+ #[doc(alias("world_name", "dimension_name"))]
+ pub fn instance_name(&self) -> InstanceName {
+ (*self.component::<InstanceName>()).clone()
}
/// A convenience function to get the Minecraft Uuid of a player by their
diff --git a/azalea/src/client_impl/movement.rs b/azalea/src/client_impl/movement.rs
index a708e5f6..6532997d 100644
--- a/azalea/src/client_impl/movement.rs
+++ b/azalea/src/client_impl/movement.rs
@@ -48,9 +48,8 @@ impl Client {
/// Returns the direction the client is looking.
///
/// See [`Self::set_direction`] for more details.
- pub fn direction(&self) -> (f32, f32) {
- let look_direction = *self.component::<LookDirection>();
- (look_direction.y_rot(), look_direction.x_rot())
+ pub fn direction(&self) -> LookDirection {
+ *self.component::<LookDirection>()
}
/// Start walking in the given direction.
diff --git a/azalea/src/container.rs b/azalea/src/container.rs
index 8b46994e..b4c98415 100644
--- a/azalea/src/container.rs
+++ b/azalea/src/container.rs
@@ -156,13 +156,13 @@ impl Client {
///
/// To open a container in the world, use [`Client::open_container_at`].
pub fn get_inventory(&self) -> ContainerHandleRef {
- self.query_self::<&Inventory, _>(|inv| ContainerHandleRef::new(inv.id, self.clone()))
+ ContainerHandleRef::new(self.component::<Inventory>().id, self.clone())
}
/// Get the item in the bot's hotbar that is currently being held in its
/// main hand.
pub fn get_held_item(&self) -> ItemStack {
- self.query_self::<&Inventory, _>(|inv| inv.held_item().clone())
+ self.component::<Inventory>().held_item().clone()
}
}
diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs
index 90fcf4dd..691fb354 100644
--- a/azalea/src/swarm/mod.rs
+++ b/azalea/src/swarm/mod.rs
@@ -256,7 +256,7 @@ impl Swarm {
"Sending SwarmEvent::Disconnect due to receiving an Event::Disconnect from client {}",
bot.entity
);
- let account = bot.component::<Account>().clone();
+ let account = bot.account();
swarm_tx
.send(SwarmEvent::Disconnect(
Box::new(account),