pub struct Client {
pub profile: GameProfile,
pub entity: Entity,
pub ecs: Arc<Mutex<RawMutex, World>>,
pub run_schedule_sender: UnboundedSender<()>,
}
Expand description
Client
has the things that a user interacting with the library will want.
To make a new client, use either azalea::ClientBuilder
or
Client::join
.
Note that Client
is inaccessible from systems (i.e. plugins), but you can
achieve everything that client can do with events.
Fields§
§profile: GameProfile
The GameProfile
for our client. This contains your username, UUID,
and skin data.
This is immutable; the server cannot change it. To get the username and
skin the server chose for you, get your player from the TabList
component.
This as also available from the ECS as GameProfileComponent
.
entity: Entity
The entity for this client in the ECS.
ecs: Arc<Mutex<RawMutex, World>>
The entity component system. You probably don’t need to access this directly. Note that if you’re using a shared world (i.e. a swarm), this will contain all entities in all worlds.
run_schedule_sender: UnboundedSender<()>
Use this to force the client to run the schedule outside of a tick.
Implementations§
Source§impl Client
impl Client
Sourcepub fn attack(&mut self, entity_id: MinecraftEntityId)
pub fn attack(&mut self, entity_id: MinecraftEntityId)
Attack the entity with the given id.
Sourcepub fn has_attack_cooldown(&self) -> bool
pub fn has_attack_cooldown(&self) -> bool
Whether the player has an attack cooldown.
Source§impl Client
impl Client
Sourcepub fn send_chat_packet(&self, message: &str)
pub fn send_chat_packet(&self, message: &str)
Send a chat message to the server. This only sends the chat packet and
not the command packet, which means on some servers you can use this to
send chat messages that start with a /
. The Client::chat
function
handles checking whether the message is a command and using the
proper packet for you, so you should use that instead.
Sourcepub fn send_command_packet(&self, command: &str)
pub fn send_command_packet(&self, command: &str)
Send a command packet to the server. The command
argument should not
include the slash at the front.
Source§impl Client
impl Client
Sourcepub fn new(
profile: GameProfile,
entity: Entity,
ecs: Arc<Mutex<RawMutex, World>>,
run_schedule_sender: UnboundedSender<()>,
) -> Client
pub fn new( profile: GameProfile, entity: Entity, ecs: Arc<Mutex<RawMutex, World>>, run_schedule_sender: UnboundedSender<()>, ) -> Client
Create a new client from the given GameProfile
, ECS Entity, ECS
World, and schedule runner function.
You should only use this if you want to change these fields from the
defaults, otherwise use Client::join
.
Sourcepub async fn join(
account: &Account,
address: impl TryInto<ServerAddress>,
) -> Result<(Client, UnboundedReceiver<Event>), JoinError>
pub async fn join( account: &Account, address: impl TryInto<ServerAddress>, ) -> Result<(Client, UnboundedReceiver<Event>), JoinError>
Connect to a Minecraft server.
To change the render distance and other settings, use
Client::set_client_information
. To watch for events like packets
sent by the server, use the rx
variable this function returns.
§Examples
use azalea_client::{Client, Account};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let account = Account::offline("bot");
let (client, rx) = Client::join(&account, "localhost").await?;
client.chat("Hello, world!");
client.disconnect();
Ok(())
}
pub async fn join_with_proxy( account: &Account, address: impl TryInto<ServerAddress>, proxy: Proxy, ) -> Result<(Client, UnboundedReceiver<Event>), JoinError>
Sourcepub async fn start_client(
__arg0: StartClientOpts<'_>,
) -> Result<(Client, UnboundedReceiver<Event>), JoinError>
pub async fn start_client( __arg0: StartClientOpts<'_>, ) -> Result<(Client, UnboundedReceiver<Event>), JoinError>
Create a Client
when you already have the ECS made with
[start_ecs_runner
]. You’d usually want to use Self::join
instead.
Sourcepub async fn handshake(
ecs_lock: Arc<Mutex<RawMutex, World>>,
entity: Entity,
conn: Connection<ClientboundHandshakePacket, ServerboundHandshakePacket>,
account: &Account,
address: &ServerAddress,
) -> Result<(Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket>, GameProfile), JoinError>
pub async fn handshake( ecs_lock: Arc<Mutex<RawMutex, World>>, entity: Entity, conn: Connection<ClientboundHandshakePacket, ServerboundHandshakePacket>, account: &Account, address: &ServerAddress, ) -> Result<(Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket>, GameProfile), JoinError>
Do a handshake with the server and get to the game state from the initial handshake state.
This will also automatically refresh the account’s access token if it’s expired.
Sourcepub fn write_packet(
&self,
packet: ServerboundGamePacket,
) -> Result<(), WritePacketError>
pub fn write_packet( &self, packet: ServerboundGamePacket, ) -> Result<(), WritePacketError>
Write a packet directly to the server.
Sourcepub fn disconnect(&self)
pub fn disconnect(&self)
Disconnect this client from the server by ending all tasks.
The OwnedReadHalf for the TCP connection is in one of the tasks, so it automatically closes the connection when that’s dropped.
pub fn raw_connection<'a>(&'a self, ecs: &'a mut World) -> &'a RawConnection
pub fn raw_connection_mut<'a>( &'a self, ecs: &'a mut World, ) -> Mut<'a, RawConnection>
Sourcepub fn get_component<T>(&self) -> Option<T>
pub fn get_component<T>(&self) -> Option<T>
Get a component from this client, or None
if it doesn’t exist.
Sourcepub fn world(&self) -> Arc<RwLock<RawRwLock, Instance>>
pub fn world(&self) -> Arc<RwLock<RawRwLock, Instance>>
Get an RwLock
with a reference to our (potentially shared) world.
This gets the Instance
from the client’s InstanceHolder
component. If it’s a normal client, then it’ll be the same as the
world the client has loaded. If the client is using a shared world,
then the shared world will be a superset of the client’s world.
Sourcepub fn partial_world(&self) -> Arc<RwLock<RawRwLock, PartialInstance>>
pub fn partial_world(&self) -> Arc<RwLock<RawRwLock, PartialInstance>>
Get an RwLock
with a reference to the world that this client has
loaded.
let world = client.partial_world();
let is_0_0_loaded = world.read().chunks.limited_get(&ChunkPos::new(0, 0)).is_some();
Sourcepub async fn set_client_information(
&self,
client_information: ClientInformation,
) -> Result<(), WritePacketError>
pub async fn set_client_information( &self, client_information: ClientInformation, ) -> Result<(), WritePacketError>
Tell the server we changed our game options (i.e. render distance, main hand). If this is not set before the login packet, the default will be sent.
bot.set_client_information(ClientInformation {
view_distance: 2,
..Default::default()
})
.await?;
Source§impl Client
impl Client
Sourcepub fn position(&self) -> Vec3
pub fn position(&self) -> Vec3
Get the position of this client.
This is a shortcut for Vec3::from(&bot.component::<Position>())
.
Sourcepub fn eye_position(&self) -> Vec3
pub fn eye_position(&self) -> Vec3
Get the position of this client’s eyes.
This is a shortcut for
bot.position().up(bot.component::<EyeHeight>())
.
Sourcepub fn health(&self) -> f32
pub fn health(&self) -> f32
Get the health of this client.
This is a shortcut for *bot.component::<Health>()
.
Sourcepub fn hunger(&self) -> Hunger
pub fn hunger(&self) -> Hunger
Get the hunger level of this client, which includes both food and saturation.
This is a shortcut for self.component::<Hunger>().to_owned()
.
Sourcepub fn username(&self) -> String
pub fn username(&self) -> String
Get the username of this client.
This is a shortcut for
bot.component::<GameProfileComponent>().name.to_owned()
.
Sourcepub fn uuid(&self) -> Uuid
pub fn uuid(&self) -> Uuid
Get the Minecraft UUID of this client.
This is a shortcut for bot.component::<GameProfileComponent>().uuid
.
Sourcepub fn tab_list(&self) -> HashMap<Uuid, PlayerInfo>
pub fn tab_list(&self) -> HashMap<Uuid, PlayerInfo>
Get a map of player UUIDs to their information in the tab list.
This is a shortcut for *bot.component::<TabList>()
.
Source§impl Client
impl Client
Sourcepub fn query<'w, D>(&self, ecs: &'w mut World) -> <D as WorldQuery>::Item<'w>where
D: QueryData,
pub fn query<'w, D>(&self, ecs: &'w mut World) -> <D as WorldQuery>::Item<'w>where
D: QueryData,
A convenience function for getting components of our player’s entity.
§Examples
let is_logged_in = client
.query::<Option<&InstanceName>>(&mut client.ecs.lock())
.is_some();
Sourcepub fn entity_by<F, Q>(
&mut self,
predicate: impl EntityPredicate<Q, F>,
) -> Option<Entity>where
F: QueryFilter,
Q: QueryData,
pub fn entity_by<F, Q>(
&mut self,
predicate: impl EntityPredicate<Q, F>,
) -> Option<Entity>where
F: QueryFilter,
Q: QueryData,
Return a lightweight Entity
for the entity that matches the given
predicate function.
You can then use Self::entity_component
to get components from this
entity.
§Example
Note that this will very likely change in the future.
use azalea_client::{Client, GameProfileComponent};
use bevy_ecs::query::With;
use azalea_entity::{Position, metadata::Player};
let entity = bot.entity_by::<With<Player>, (&GameProfileComponent,)>(
|(profile,): &(&GameProfileComponent,)| profile.name == sender_name,
);
if let Some(entity) = entity {
let position = bot.entity_component::<Position>(entity);
// ...
}
Sourcepub fn entity_component<Q>(&mut self, entity: Entity) -> Q
pub fn entity_component<Q>(&mut self, entity: Entity) -> Q
Get a component from an entity. Note that this will return an owned type (i.e. not a reference) so it may be expensive for larger types.
If you’re trying to get a component for this client, use
Self::component
.
Sourcepub fn get_entity_component<Q>(&mut self, entity: Entity) -> Option<Q>
pub fn get_entity_component<Q>(&mut self, entity: Entity) -> Option<Q>
Get a component from an entity, if it exists. This is similar to
Self::entity_component
but returns an Option
instead of panicking
if the component isn’t present.
Source§impl Client
impl Client
Sourcepub fn block_interact(&mut self, position: BlockPos)
pub fn block_interact(&mut self, position: BlockPos)
Right click a block. The behavior of this depends on the target block, and it’ll either place the block you’re holding in your hand or use the block you clicked (like toggling a lever).
Note that this may trigger anticheats as it doesn’t take into account whether you’re actually looking at the block.
Source§impl Client
impl Client
Return the menu that is currently open. If no menu is open, this will have the player’s inventory.
Source§impl Client
impl Client
pub fn start_mining(&mut self, position: BlockPos)
Sourcepub fn left_click_mine(&self, enabled: bool)
pub fn left_click_mine(&self, enabled: bool)
When enabled, the bot will mine any block that it is looking at if it is reachable.
Source§impl Client
impl Client
Sourcepub fn set_jumping(&mut self, jumping: bool)
pub fn set_jumping(&mut self, jumping: bool)
Set whether we’re jumping. This acts as if you held space in
vanilla. If you want to jump once, use the jump
function.
If you’re making a realistic client, calling this function every tick is recommended.
Sourcepub fn set_direction(&mut self, y_rot: f32, x_rot: f32)
pub fn set_direction(&mut self, y_rot: f32, x_rot: f32)
Sets the direction the client is looking. y_rot
is yaw (looking to the
side), x_rot
is pitch (looking up and down). You can get these
numbers from the vanilla f3 screen.
y_rot
goes from -180 to 180, and x_rot
goes from -90 to 90.
Source§impl Client
impl Client
Sourcepub fn walk(&mut self, direction: WalkDirection)
pub fn walk(&mut self, direction: WalkDirection)
Start walking in the given direction. To sprint, use
Client::sprint
. To stop walking, call walk with
WalkDirection::None
.
§Examples
Walk for 1 second
bot.walk(WalkDirection::Forward);
tokio::time::sleep(Duration::from_secs(1)).await;
bot.walk(WalkDirection::None);
Sourcepub fn sprint(&mut self, direction: SprintDirection)
pub fn sprint(&mut self, direction: SprintDirection)
Start sprinting in the given direction. To stop moving, call
[Client::walk(WalkDirection::None)
]
§Examples
Sprint for 1 second
bot.sprint(SprintDirection::Forward);
tokio::time::sleep(Duration::from_secs(1)).await;
bot.walk(WalkDirection::None);
Trait Implementations§
Source§impl AutoToolClientExt for Client
impl AutoToolClientExt for Client
fn best_tool_in_hotbar_for_block(&self, block: BlockState) -> BestToolResult
Source§impl BotClientExt for Client
impl BotClientExt for Client
Source§fn get_tick_broadcaster(&self) -> Receiver<()>
fn get_tick_broadcaster(&self) -> Receiver<()>
let mut ticks = bot.get_tick_broadcaster();
while ticks.recv().await.is_ok() {
let ecs = bot.ecs.lock();
if ecs.get::<WaitingForInventoryOpen>(bot.entity).is_none() {
break;
}
}
Source§impl ContainerClientExt for Client
impl ContainerClientExt for Client
Source§async fn open_container_at(&mut self, pos: BlockPos) -> Option<ContainerHandle>
async fn open_container_at(&mut self, pos: BlockPos) -> Option<ContainerHandle>
Open a container in the world, like a chest. Use
Client::open_inventory
to open your own inventory.
let target_pos = bot
.world()
.read()
.find_block(bot.position(), &azalea::registry::Block::Chest.into());
let Some(target_pos) = target_pos else {
bot.chat("no chest found");
return;
};
let container = bot.open_container_at(target_pos).await;
Source§fn open_inventory(&mut self) -> Option<ContainerHandle>
fn open_inventory(&mut self) -> Option<ContainerHandle>
Open the player’s inventory. This will return None if another container is open.
Note that this will send a packet to the server once it’s dropped. Also, due to how it’s implemented, you could call this function multiple times while another inventory handle already exists (but you shouldn’t).
If you just want to get the items in the player’s inventory without
sending any packets, use Client::menu
, Menu::player_slots_range
,
and Menu::slots
.
Source§fn get_open_container(&self) -> Option<ContainerHandleRef>
fn get_open_container(&self) -> Option<ContainerHandleRef>
Get a handle to the open container. This will return None if no container is open. This will not close the container when it’s dropped.
See Client::open_inventory
or Client::menu
if you want to open
your own inventory.
Source§impl PathfinderClientExt for Client
impl PathfinderClientExt for Client
Auto Trait Implementations§
impl Freeze for Client
impl !RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl !UnwindSafe for Client
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> Downcast for Twhere
T: AsAny + ?Sized,
impl<T> Downcast for Twhere
T: AsAny + ?Sized,
§fn downcast_ref<T>(&self) -> Option<&T>where
T: AsAny,
fn downcast_ref<T>(&self) -> Option<&T>where
T: AsAny,
Any
.§fn downcast_mut<T>(&mut self) -> Option<&mut T>where
T: AsAny,
fn downcast_mut<T>(&mut self) -> Option<&mut T>where
T: AsAny,
Any
.