diff options
| author | mat <git@matdoes.dev> | 2025-12-28 09:06:47 -0330 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2025-12-28 09:06:47 -0330 |
| commit | 839d536e8020b291bc1d213a5e8e823dc513a940 (patch) | |
| tree | 60cab8b908ad53af0126e2cb1dec670d073936a3 | |
| parent | 5b1a78baf757897532be8c308a37c99fb2ca3352 (diff) | |
| download | azalea-drasl-839d536e8020b291bc1d213a5e8e823dc513a940.tar.xz | |
add a few more functions for getting common components to Client
| -rw-r--r-- | azalea/examples/steal.rs | 4 | ||||
| -rw-r--r-- | azalea/examples/testbot/commands/debug.rs | 8 | ||||
| -rw-r--r-- | azalea/examples/testbot/killaura.rs | 33 | ||||
| -rw-r--r-- | azalea/examples/todo/craft_dig_straight_down.rs | 5 | ||||
| -rw-r--r-- | azalea/src/client_impl/entity_query.rs | 31 | ||||
| -rw-r--r-- | azalea/src/client_impl/interact.rs | 10 | ||||
| -rw-r--r-- | azalea/src/client_impl/inventory.rs | 7 | ||||
| -rw-r--r-- | azalea/src/client_impl/mod.rs | 24 | ||||
| -rw-r--r-- | azalea/src/client_impl/movement.rs | 5 | ||||
| -rw-r--r-- | azalea/src/container.rs | 4 | ||||
| -rw-r--r-- | azalea/src/swarm/mod.rs | 2 |
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), |
