mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
write more documentation
This commit is contained in:
parent
127126c2cc
commit
a9ff79a105
15 changed files with 167 additions and 41 deletions
|
@ -48,7 +48,7 @@ pub enum AuthError {
|
|||
GetXboxLiveAuth(#[from] XboxLiveAuthError),
|
||||
}
|
||||
|
||||
/// Authenticate with authenticate with Microsoft. If the data isn't cached,
|
||||
/// Authenticate with Microsoft. If the data isn't cached,
|
||||
/// they'll be asked to go to log into Microsoft in a web page.
|
||||
///
|
||||
/// The email is technically only used as a cache key, so it *could* be
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
/// A Vec<u8> that isn't prefixed by a VarInt with the size.
|
||||
/// A `Vec<u8>` that isn't prefixed by a VarInt with the size.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct UnsizedByteArray(pub Vec<u8>);
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
//! Connect to Minecraft servers.
|
||||
|
||||
use crate::{client::JoinError, get_mc_dir, Client, Event};
|
||||
use azalea_protocol::ServerAddress;
|
||||
use tokio::sync::mpsc::UnboundedReceiver;
|
||||
use crate::get_mc_dir;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Something that can join Minecraft servers.
|
||||
///
|
||||
/// To join a server using this account, use [`crate::Client::join`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Account {
|
||||
/// The Minecraft username of the account.
|
||||
pub username: String,
|
||||
/// The access token for authentication. You can obtain one of these
|
||||
/// manually from azalea-auth.
|
||||
|
@ -15,7 +16,11 @@ pub struct Account {
|
|||
/// Only required for online-mode accounts.
|
||||
pub uuid: Option<uuid::Uuid>,
|
||||
}
|
||||
|
||||
impl Account {
|
||||
/// An offline account does not authenticate with Microsoft's servers, and
|
||||
/// as such can only join offline mode servers. This is useful for testing
|
||||
/// in LAN worlds.
|
||||
pub fn offline(username: &str) -> Self {
|
||||
Self {
|
||||
username: username.to_string(),
|
||||
|
@ -24,6 +29,10 @@ impl Account {
|
|||
}
|
||||
}
|
||||
|
||||
/// This will create an online-mode account by authenticating with
|
||||
/// Microsoft's servers. Note that the email given is actually only used as
|
||||
/// a key for the cache, but it's recommended to use the real email to
|
||||
/// avoid confusion.
|
||||
pub async fn microsoft(email: &str) -> Result<Self, azalea_auth::AuthError> {
|
||||
let minecraft_dir = get_mc_dir::minecraft_dir().unwrap();
|
||||
let auth_result = azalea_auth::auth(
|
||||
|
@ -40,12 +49,4 @@ impl Account {
|
|||
uuid: Some(Uuid::parse_str(&auth_result.profile.id).expect("Invalid UUID")),
|
||||
})
|
||||
}
|
||||
|
||||
/// Joins the Minecraft server on the given address using this account.
|
||||
pub async fn join(
|
||||
&self,
|
||||
address: &ServerAddress,
|
||||
) -> Result<(Client, UnboundedReceiver<Event>), JoinError> {
|
||||
Client::join(self, address).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,9 @@ use crate::Client;
|
|||
|
||||
impl Client {
|
||||
/// Sends chat message to the server. This only sends the chat packet and
|
||||
/// not the command packet. The `chat` function handles checking whether
|
||||
/// the message is a command and using the proper packet for you.
|
||||
/// not the command packet. 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.
|
||||
pub async fn send_chat_packet(&self, message: &str) -> Result<(), std::io::Error> {
|
||||
// TODO: chat signing
|
||||
let signature = sign_message();
|
||||
|
@ -54,6 +55,33 @@ impl Client {
|
|||
self.write_packet(packet).await
|
||||
}
|
||||
|
||||
/// Send a message in chat.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # use azalea::prelude::*;
|
||||
/// # use parking_lot::Mutex;
|
||||
/// # use std::sync::Arc;
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main() {
|
||||
/// # let account = Account::offline("bot");
|
||||
/// # azalea::start(azalea::Options {
|
||||
/// # account,
|
||||
/// # address: "localhost",
|
||||
/// # state: Arc::new(Mutex::new(State::default())),
|
||||
/// # plugins: vec![],
|
||||
/// # handle,
|
||||
/// # })
|
||||
/// # .await
|
||||
/// # .unwrap();
|
||||
/// # }
|
||||
/// # pub struct State {}
|
||||
/// # async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||
/// bot.chat("Hello, world!").await.unwrap();
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub async fn chat(&self, message: &str) -> Result<(), std::io::Error> {
|
||||
if message.chars().next() == Some('/') {
|
||||
self.send_command_packet(&message[1..]).await
|
||||
|
|
|
@ -69,7 +69,7 @@ impl ChatPacket {
|
|||
}
|
||||
}
|
||||
|
||||
/// A player that you can control that is currently in a Minecraft server.
|
||||
/// A player that you control that is currently in a Minecraft server.
|
||||
#[derive(Clone)]
|
||||
pub struct Client {
|
||||
game_profile: GameProfile,
|
||||
|
@ -106,6 +106,8 @@ pub enum JoinError {
|
|||
Io(#[from] io::Error),
|
||||
#[error("{0}")]
|
||||
SessionServer(#[from] azalea_auth::sessionserver::SessionServerError),
|
||||
#[error("The given address could not be parsed into a ServerAddress")]
|
||||
InvalidAddress,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
@ -119,12 +121,26 @@ pub enum HandleError {
|
|||
}
|
||||
|
||||
impl Client {
|
||||
/// Connect to a Minecraft server with an account.
|
||||
/// Connect to a Minecraft server.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use azalea_client::Client;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> Box<dyn std::error::Error> {
|
||||
/// let account = Account::offline("bot");
|
||||
/// let client = Client::join(&account, "localhost").await?;
|
||||
/// client.chat("Hello, world!").await?;
|
||||
/// client.shutdown().await?;
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn join(
|
||||
account: &Account,
|
||||
address: &ServerAddress,
|
||||
address: impl TryInto<ServerAddress>,
|
||||
) -> Result<(Self, UnboundedReceiver<Event>), JoinError> {
|
||||
let resolved_address = resolver::resolve_address(address).await?;
|
||||
let address: ServerAddress = address.try_into().map_err(|_| JoinError::InvalidAddress)?;
|
||||
|
||||
let resolved_address = resolver::resolve_address(&address).await?;
|
||||
|
||||
let mut conn = Connection::new(&resolved_address).await?;
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
//! Significantly abstract azalea-protocol so it's actually useable for bots.
|
||||
//! Significantly abstract [`azalea_protocol`] so it's actually useable for
|
||||
//! real clients. If you want to make bots, however, you should use the
|
||||
//! [`azalea`] crate instead.
|
||||
//!
|
||||
//! [`azalea_protocol`]: https://crates.io/crates/azalea-protocol
|
||||
//! [`azalea`]: https://crates.io/crates/azalea
|
||||
|
||||
mod account;
|
||||
mod chat;
|
||||
|
|
|
@ -155,6 +155,8 @@ impl Client {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Makes the bot do one physics tick. Note that this is already handled
|
||||
/// automatically by the client.
|
||||
pub fn ai_step(&mut self) {
|
||||
self.tick_controls(None);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
///! Ping Minecraft servers.
|
||||
//! Ping Minecraft servers.
|
||||
|
||||
use azalea_protocol::{
|
||||
connect::{Connection, ConnectionError},
|
||||
packets::{
|
||||
|
@ -25,12 +26,27 @@ pub enum PingError {
|
|||
ReadPacket(#[from] azalea_protocol::read::ReadPacketError),
|
||||
#[error("{0}")]
|
||||
WritePacket(#[from] io::Error),
|
||||
#[error("The given address could not be parsed into a ServerAddress")]
|
||||
InvalidAddress,
|
||||
}
|
||||
|
||||
/// Ping a Minecraft server.
|
||||
///
|
||||
/// ```
|
||||
/// use azalea_client::ping;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let response = ping::ping_server("play.hypixel.net").await.unwrap();
|
||||
/// println!("{}", response.description.to_ansi(None));
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn ping_server(
|
||||
address: &ServerAddress,
|
||||
address: impl TryInto<ServerAddress>,
|
||||
) -> Result<ClientboundStatusResponsePacket, PingError> {
|
||||
let resolved_address = resolver::resolve_address(address).await?;
|
||||
let address: ServerAddress = address.try_into().map_err(|_| PingError::InvalidAddress)?;
|
||||
|
||||
let resolved_address = resolver::resolve_address(&address).await?;
|
||||
|
||||
let mut conn = Connection::new(&resolved_address).await?;
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
|||
/// online-mode servers. This must happen when you get a
|
||||
/// `ClientboundLoginPacket::Hello` packet.
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```rust,no_run
|
||||
/// let token = azalea_auth::auth(azalea_auth::AuthOpts {
|
||||
/// ..Default::default()
|
||||
/// })
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
A framework for creating Minecraft bots.
|
||||
Azalea is a framework for creating Minecraft bots.
|
||||
|
||||
Interally, it's just a wrapper over azalea-client, adding useful functions for making bots.
|
||||
Internally, it's just a wrapper over azalea-client, adding useful functions for making bots.
|
||||
|
|
|
@ -11,7 +11,7 @@ struct State {
|
|||
#[tokio::main]
|
||||
async fn main() {
|
||||
let account = Account::offline("bot");
|
||||
// or let bot = Account::microsoft("access token").await;
|
||||
// or let bot = Account::microsoft("email").await;
|
||||
|
||||
azalea::start(azalea::Options {
|
||||
account,
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use std::sync::Arc;
|
||||
//! A simple bot that repeats chat messages sent by other players.
|
||||
|
||||
use azalea::{Account, Client, Event};
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let account = Account::offline("bot");
|
||||
// or let account = Account::microsoft("access token").await;
|
||||
// or let account = Account::microsoft("email").await;
|
||||
|
||||
azalea::start(azalea::Options {
|
||||
account,
|
||||
|
@ -22,7 +23,7 @@ async fn main() {
|
|||
pub struct State {}
|
||||
|
||||
async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||
match event {
|
||||
match *event {
|
||||
Event::Chat(m) => {
|
||||
if m.username == bot.username {
|
||||
return Ok(()); // ignore our own messages
|
||||
|
@ -33,12 +34,6 @@ async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> any
|
|||
println!(m);
|
||||
bot.reconnect().await.unwrap();
|
||||
}
|
||||
Event::HungerUpdate(h) => {
|
||||
if !h.using_held_item() && h.hunger <= 17 {
|
||||
bot.hold(azalea::ItemGroup::Food).await?;
|
||||
bot.use_held_item().await?;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use azalea::{pathfinder, Account, Accounts, Client, Event};
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
|
|
@ -1,3 +1,51 @@
|
|||
//! Azalea is a framework for creating Minecraft bots.
|
||||
//!
|
||||
//! Internally, it's just a wrapper over [`azalea_client`], adding useful
|
||||
//! functions for making bots. Because of this, lots 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
|
||||
//! //! A bot that logs chat messages sent in the server to the console.
|
||||
//!
|
||||
//! use azalea::prelude::*;
|
||||
//! use parking_lot::Mutex;
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() {
|
||||
//! let account = Account::offline("bot");
|
||||
//! // or Account::microsoft("example@example.com").await.unwrap();
|
||||
//!
|
||||
//! azalea::start(azalea::Options {
|
||||
//! account,
|
||||
//! address: "localhost",
|
||||
//! state: Arc::new(Mutex::new(State::default())),
|
||||
//! plugins: vec![],
|
||||
//! handle,
|
||||
//! })
|
||||
//! .await
|
||||
//! .unwrap();
|
||||
//! }
|
||||
//!
|
||||
//! pub struct State {}
|
||||
//!
|
||||
//! async fn handle(bot: Client, event: Arc<Event>, state: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||
//! match *event {
|
||||
//! Event::Chat(m) => {
|
||||
//! println!(m.message().to_ansi(None));
|
||||
//! }
|
||||
//! _ => {}
|
||||
//! }
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! [`azalea_client`]: https://crates.io/crates/azalea-client
|
||||
|
||||
mod bot;
|
||||
pub mod prelude;
|
||||
|
||||
|
@ -16,15 +64,27 @@ pub trait Plugin: Send + Sync {
|
|||
|
||||
pub type HandleFn<Fut, S> = fn(Client, Arc<Event>, Arc<Mutex<S>>) -> Fut;
|
||||
|
||||
/// The options that are passed to [`azalea::start`].
|
||||
///
|
||||
/// [`azalea::start`]: fn.start.html
|
||||
pub struct Options<S, A, Fut>
|
||||
where
|
||||
A: TryInto<ServerAddress>,
|
||||
Fut: Future<Output = Result<(), anyhow::Error>>,
|
||||
{
|
||||
/// The address of the server that we're connecting to. This can be a
|
||||
/// `&str`, [`ServerAddress`], or anything that implements
|
||||
/// `TryInto<ServerAddress>`.
|
||||
pub address: A,
|
||||
/// The account that's going to join the server,
|
||||
pub account: Account,
|
||||
/// A list of plugins that are going to be used. Plugins are external
|
||||
/// crates that add extra functionality to Azalea.
|
||||
pub plugins: Vec<Arc<dyn Plugin>>,
|
||||
/// A struct that contains the data that you want your bot to remember
|
||||
/// across events.
|
||||
pub state: Arc<Mutex<S>>,
|
||||
/// The function that's called whenever we get an event.
|
||||
pub handle: HandleFn<Fut, S>,
|
||||
}
|
||||
|
||||
|
@ -34,9 +94,10 @@ pub enum Error {
|
|||
InvalidAddress,
|
||||
}
|
||||
|
||||
/// Join a Minecraft server.
|
||||
/// Join a server and start handling events. This function will run forever until
|
||||
/// it gets disconnected from the server.
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```rust,no_run
|
||||
/// azalea::start(azalea::Options {
|
||||
/// account,
|
||||
/// address: "localhost",
|
||||
|
@ -57,7 +118,7 @@ pub async fn start<
|
|||
Err(_) => return Err(Error::InvalidAddress),
|
||||
};
|
||||
|
||||
let (bot, mut rx) = options.account.join(&address).await.unwrap();
|
||||
let (bot, mut rx) = Client::join(&options.account, address).await.unwrap();
|
||||
|
||||
let state = options.state;
|
||||
let bot_plugin = Arc::new(bot::Plugin::default());
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
//! The Azalea prelude.
|
||||
|
||||
pub use crate::bot::BotTrait;
|
||||
pub use azalea_client::{Account, Client, Event};
|
||||
|
|
Loading…
Add table
Reference in a new issue