diff options
| -rw-r--r-- | CHANGELOG.md | 4 | ||||
| -rw-r--r-- | azalea-chat/src/component.rs | 15 | ||||
| -rw-r--r-- | azalea-client/src/account.rs | 4 | ||||
| -rw-r--r-- | azalea-client/src/entity_query.rs | 58 | ||||
| -rw-r--r-- | azalea-client/src/plugins/movement.rs | 2 | ||||
| -rw-r--r-- | azalea-entity/src/lib.rs | 27 | ||||
| -rw-r--r-- | azalea-inventory/src/default_components/mod.rs | 3 | ||||
| -rw-r--r-- | azalea-inventory/src/operations.rs | 1 | ||||
| -rw-r--r-- | azalea/README.md | 7 | ||||
| -rw-r--r-- | azalea/examples/testbot/commands.rs | 7 | ||||
| -rw-r--r-- | azalea/src/container.rs | 4 | ||||
| -rw-r--r-- | azalea/src/pathfinder/goto_event.rs | 5 |
12 files changed, 101 insertions, 36 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 979a1ad5..5850f181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ is breaking anyways, semantic versioning is not followed. - Local clients now have a `TicksConnected` component. (@Kumpelinus) - There is now a `azalea_inventory::default_components::get_default_component` function to get the default value of a component for a registry item. - `ItemStack` now has a `get_component` function that supports default components. +- Add `Client::nearest_entity_by`. ### Changed @@ -24,18 +25,19 @@ is breaking anyways, semantic versioning is not followed. - `Client::attack` now takes `Entity` instead of `MinecraftEntityId`. - `ItemStackData::components` was renamed to `component_patch`. - The fields in `LookDirection` have been replaced with getters. +- Renamed `Client::entity_by` to `any_entity_by`, and `Client::entities_by` to `nearest_entities_by`. ### Fixed - Fix packet order for loading (`PlayerLoaded`/`MovePlayerPos`) and sprinting (`PlayerInput`/`PlayerCommand`). - Clients no longer send invalid look directions if the server teleports us with one. +- Look directions are now rounded based on the default Minecraft sensitivity, which may help avoid flagging anticheats. - Movement code was updated with the changes from 1.21.5, so it no longer flags Grim. - `azalea-chat` now handles arrays of integers in the `with` field. (@qwqawawow) - `azalea-chat` no longer incorrectly persists styles of components in the "extra" field. - Inventories now use the correct max stack sizes. - Clients now send the correct data component checksums when interacting with items. - Fix parsing some metadata fields of Display entities. -- Look directions are now rounded based on the default Minecraft sensitivity, which may help avoid flagging anticheats. ## [0.13.0+mc1.21.5] - 2025-06-15 diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs index bf064c8f..62e5e151 100644 --- a/azalea-chat/src/component.rs +++ b/azalea-chat/src/component.rs @@ -131,7 +131,6 @@ impl FormattedText { &mut output, &mut style_formatter, &mut text_formatter, - &mut cleanup_formatter, &default_style.clone(), &mut running_style, ); @@ -140,18 +139,16 @@ impl FormattedText { output } - fn to_custom_format_recursive<F, S, C>( + fn to_custom_format_recursive<F, S>( &self, output: &mut String, style_formatter: &mut F, text_formatter: &mut S, - cleanup_formatter: &mut C, parent_style: &Style, running_style: &mut Style, ) where F: FnMut(&Style, &Style) -> (String, String), S: FnMut(&str) -> String, - C: FnMut(&Style) -> String, { let component_text = match &self { Self::Text(c) => c.text.to_string(), @@ -166,7 +163,7 @@ impl FormattedText { if !component_text.is_empty() { let (formatted_style_prefix, formatted_style_suffix) = - style_formatter(&running_style, &new_style); + style_formatter(running_style, &new_style); let formatted_text = text_formatter(&component_text); output.push_str(&formatted_style_prefix); @@ -181,7 +178,6 @@ impl FormattedText { output, style_formatter, text_formatter, - cleanup_formatter, &new_style, running_style, ); @@ -211,7 +207,7 @@ impl FormattedText { /// colored white. /// /// If you don't want the result to be styled at all, use - /// [`Self::to_string`]. + /// [`Self::to_string`](#method.fmt-1). /// /// # Examples /// @@ -230,6 +226,7 @@ impl FormattedText { self.to_ansi_with_custom_style(&DEFAULT_STYLE) } + /// Similar to [`Self::to_ansi`] but renders the result as HTML instead. pub fn to_html(&self) -> String { self.to_custom_format( |running, new| { @@ -664,6 +661,10 @@ impl From<TextComponent> for FormattedText { } impl Display for FormattedText { + /// Render the text in the component but without any formatting/styling. + /// + /// If you want the text to be styled, consider using [`Self::to_ansi`] or + /// [`Self::to_html`]. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { FormattedText::Text(c) => c.fmt(f), diff --git a/azalea-client/src/account.rs b/azalea-client/src/account.rs index 7e3f917d..bda69558 100644 --- a/azalea-client/src/account.rs +++ b/azalea-client/src/account.rs @@ -22,8 +22,8 @@ use uuid::Uuid; /// # Examples /// /// ```rust,no_run -/// use azalea_client::Account; -/// +/// # use azalea_client::Account; +/// # /// # #[tokio::main] /// # async fn main() { /// let account = Account::microsoft("example@example.com").await; diff --git a/azalea-client/src/entity_query.rs b/azalea-client/src/entity_query.rs index ee99d0f4..49119b98 100644 --- a/azalea-client/src/entity_query.rs +++ b/azalea-client/src/entity_query.rs @@ -36,15 +36,16 @@ impl Client { }) } - /// Return a lightweight [`Entity`] for an arbitrary entity that matches the - /// given predicate function that is in the same [`Instance`] as the - /// client. + /// Quickly returns a lightweight [`Entity`] for an arbitrary entity that + /// matches the given predicate function that is in the same + /// [`Instance`] as the client. /// /// You can then use [`Self::entity_component`] to get components from this /// entity. /// - /// Also see [`Self::entities_by`] which will return all entities that match - /// the predicate and sorts them by distance (unlike `entity_by`). + /// If you want to find the nearest entity, consider using + /// [`Self::nearest_entity_by`] instead. If you want to find all entities + /// that match the predicate, use [`Self::nearest_entities_by`]. /// /// # Example /// ``` @@ -65,7 +66,7 @@ impl Client { /// /// [`Entity`]: bevy_ecs::entity::Entity /// [`Instance`]: azalea_world::Instance - pub fn entity_by<F: QueryFilter, Q: QueryData>( + pub fn any_entity_by<F: QueryFilter, Q: QueryData>( &self, predicate: impl EntityPredicate<Q, F>, ) -> Option<Entity> { @@ -73,12 +74,47 @@ impl Client { predicate.find_any(self.ecs.clone(), &instance_name) } - /// Similar to [`Self::entity_by`] but returns a `Vec<Entity>` of all - /// entities in our instance that match the predicate. + /// Return a lightweight [`Entity`] for the nearest entity that matches the + /// given predicate function. /// - /// Unlike `entity_by`, the result is sorted by distance to our client's - /// position, so the closest entity is first. - pub fn entities_by<F: QueryFilter, Q: QueryData>( + /// You can then use [`Self::entity_component`] to get components from this + /// entity. + /// + /// If you don't need the entity to be the nearest one, it may be more + /// efficient to use [`Self::any_entity_by`] instead. You can also use + /// [`Self::nearest_entities_by`] to get all nearby entities. + /// + /// # Example + /// ``` + /// use azalea_entity::{Position, metadata::Player, LocalEntity}; + /// use bevy_ecs::query::With; + /// + /// # fn example(mut bot: azalea_client::Client, sender_name: String) { + /// // look at the nearest player + /// if let Some(closest_player) = bot + /// .entities_by::<(With<Player>, Without<LocalEntity>), ()>(|_: &()| true) + /// .first() + /// { + /// let closest_player_pos = *bot.entity_component::<Position>(*closest_player); + /// bot.look_at(closest_player_pos.up(1.62)); + /// } + /// } + /// ``` + /// + /// [`Entity`]: bevy_ecs::entity::Entity + /// [`Instance`]: azalea_world::Instance + pub fn nearest_entity_by<F: QueryFilter, Q: QueryData>( + &self, + predicate: impl EntityPredicate<Q, F>, + ) -> Option<Entity> { + self.nearest_entities_by(predicate).first().copied() + } + + /// Similar to [`Self::nearest_entity_by`] but returns a `Vec<Entity>` of + /// all entities in our instance that match the predicate. + /// + /// The first entity is the nearest one. + pub fn nearest_entities_by<F: QueryFilter, Q: QueryData>( &self, predicate: impl EntityPredicate<Q, F>, ) -> Vec<Entity> { diff --git a/azalea-client/src/plugins/movement.rs b/azalea-client/src/plugins/movement.rs index c27a67ce..675796f6 100644 --- a/azalea-client/src/plugins/movement.rs +++ b/azalea-client/src/plugins/movement.rs @@ -452,7 +452,7 @@ impl Client { } /// Start sprinting in the given direction. To stop moving, call - /// [`Client::walk(WalkDirection::None)`] + /// [`bot.walk(WalkDirection::None)`](Self::walk) /// /// # Examples /// diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs index 8758c258..645a5534 100644 --- a/azalea-entity/src/lib.rs +++ b/azalea-entity/src/lib.rs @@ -230,8 +230,7 @@ pub struct LookDirection { } impl LookDirection { - /// Create a new look direction, while clamping and wrapping the rotations - /// to the allowed values. + /// Create a new look direction and clamp the `x_rot` to the allowed values. pub fn new(y_rot: f32, x_rot: f32) -> Self { apply_clamp_look_direction(Self { y_rot, x_rot }) } @@ -255,12 +254,32 @@ impl LookDirection { pub fn update(&mut self, new: LookDirection) { self.update_with_sensitivity(new, 1.); } + /// Update the `y_rot` to the given value, in degrees. + /// + /// This is a shortcut for [`Self::update`] while keeping the `x_rot` the + /// same. + pub fn update_y_rot(&mut self, new_y_rot: f32) { + self.update(LookDirection { + y_rot: new_y_rot, + x_rot: self.x_rot, + }); + } + /// Update the `x_rot` to the given value, in degrees. + /// + /// This is a shortcut for [`Self::update`] while keeping the `y_rot` the + /// same. + pub fn update_x_rot(&mut self, new_x_rot: f32) { + self.update(LookDirection { + y_rot: self.y_rot, + x_rot: new_x_rot, + }); + } /// Update this look direction to the new value, using the given /// sensitivity value. /// - /// Consider using [`Self::set`] instead, which uses 1.0 as the sensitivity - /// (equivalent to 100% sensitivity in Minecraft). + /// Consider using [`Self::update`] instead, which uses 1.0 as the + /// sensitivity (equivalent to 100% sensitivity in Minecraft). pub fn update_with_sensitivity(&mut self, new: LookDirection, sensitivity: f32) { let mut delta_y_rot = new.y_rot.rem_euclid(360.) - self.y_rot.rem_euclid(360.); let delta_x_rot = new.x_rot - self.x_rot; diff --git a/azalea-inventory/src/default_components/mod.rs b/azalea-inventory/src/default_components/mod.rs index 7f9ef6fb..74b7248e 100644 --- a/azalea-inventory/src/default_components/mod.rs +++ b/azalea-inventory/src/default_components/mod.rs @@ -4,7 +4,8 @@ use azalea_registry::Item; use crate::components::DataComponentTrait; -/// A [`DataComponent`] that some [`Item`]s may have a default value for. +/// A trait for data components that some [`Item`]s may have a default value +/// for. pub trait DefaultableComponent: DataComponentTrait { fn default_for_item(item: Item) -> Option<Self> where diff --git a/azalea-inventory/src/operations.rs b/azalea-inventory/src/operations.rs index e7668ab5..60bf9e64 100644 --- a/azalea-inventory/src/operations.rs +++ b/azalea-inventory/src/operations.rs @@ -13,6 +13,7 @@ use crate::{ StonecutterMenuLocation, item::MaxStackSizeExt, }; +/// A type of click in a Minecraft inventory. #[derive(Debug, Clone)] pub enum ClickOperation { Pickup(PickupClick), diff --git a/azalea/README.md b/azalea/README.md index 4f7506d1..3454ed2e 100644 --- a/azalea/README.md +++ b/azalea/README.md @@ -32,10 +32,6 @@ opt-level = 3 The documentation for the latest Azalea crates.io release is available at [docs.rs/azalea](https://docs.rs/azalea/latest/azalea/) and the docs for the latest bleeding-edge (git) version are at [azalea.matdoes.dev](https://azalea.matdoes.dev/azalea/). -Note that the `azalea` crate is technically just a wrapper over [`azalea_client`] that adds some extra functions. -Because of this, some of the documentation will refer to `azalea_client`. -You can just replace these with `azalea` in your code since everything from `azalea_client` is re-exported in azalea. - # Examples ```rust,no_run @@ -76,6 +72,9 @@ async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> { } ``` +There are more examples in the [examples directory](https://github.com/azalea-rs/azalea/tree/main/azalea/examples). +You may also find it helpful to read the code for [other people's Azalea bots](https://github.com/azalea-rs/azalea#real-world-bots-using-azalea). + # Swarms Azalea lets you create "swarms", which are a group of bots in the same world that can perform actions together. See [testbot](https://github.com/azalea-rs/azalea/blob/main/azalea/examples/testbot/main.rs) for an example. Also, if you're using swarms, you should also `use` both `azalea::prelude::*` and `azalea::swarm::prelude::*`. diff --git a/azalea/examples/testbot/commands.rs b/azalea/examples/testbot/commands.rs index ecd68ade..7486780e 100644 --- a/azalea/examples/testbot/commands.rs +++ b/azalea/examples/testbot/commands.rs @@ -31,9 +31,10 @@ impl CommandSource { pub fn entity(&mut self) -> Option<Entity> { let username = self.chat.sender()?; - self.bot.entity_by::<With<Player>, &GameProfileComponent>( - |profile: &&GameProfileComponent| profile.name == username, - ) + self.bot + .any_entity_by::<With<Player>, &GameProfileComponent>( + |profile: &&GameProfileComponent| profile.name == username, + ) } } diff --git a/azalea/src/container.rs b/azalea/src/container.rs index ee618df2..a7b496ea 100644 --- a/azalea/src/container.rs +++ b/azalea/src/container.rs @@ -174,7 +174,7 @@ impl ContainerHandleRef { /// /// Note that any modifications you make to the `Menu` you're given will not /// actually cause any packets to be sent. If you're trying to modify your - /// inventory, use [`ContainerHandle::click`] instead + /// inventory, use [`Self::click`] instead pub fn menu(&self) -> Option<Menu> { let ecs = self.client.ecs.lock(); let inventory = ecs @@ -224,6 +224,8 @@ impl ContainerHandleRef { }); } + /// Simulate a click in the container and send the packet to perform the + /// action. pub fn click(&self, operation: impl Into<ClickOperation>) { let operation = operation.into(); self.client.ecs.lock().send_event(ContainerClickEvent { diff --git a/azalea/src/pathfinder/goto_event.rs b/azalea/src/pathfinder/goto_event.rs index dfd89122..d87d1586 100644 --- a/azalea/src/pathfinder/goto_event.rs +++ b/azalea/src/pathfinder/goto_event.rs @@ -12,7 +12,10 @@ use crate::pathfinder::{ /// /// Also see [`PathfinderClientExt::goto`]. /// -/// This event is read by [`goto_listener`]. +/// This event is read by [`goto_listener`] +/// +/// [`goto_listener`]: crate::pathfinder::goto_listener +/// [`PathfinderClientExt::goto`]: crate::pathfinder::PathfinderClientExt::goto #[derive(Event)] #[non_exhaustive] pub struct GotoEvent { |
