fix and improve examples in docs

This commit is contained in:
Ubuntu 2023-02-10 18:06:18 +00:00
parent 7e43e6d24a
commit f5ae1b9717
7 changed files with 94 additions and 26 deletions

View file

@ -470,7 +470,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
let Some(default_state_id) = default_state_id else { let Some(default_state_id) = default_state_id else {
let defaults = properties_with_name.iter().map(|p| if let TokenTree::Ident(i) = p.default.clone().into_iter().last().unwrap() { i.to_string() } else { panic!() }).collect::<Vec<_>>(); let defaults = properties_with_name.iter().map(|p| if let TokenTree::Ident(i) = p.default.clone().into_iter().last().unwrap() { i.to_string() } else { panic!() }).collect::<Vec<_>>();
panic!("Couldn't get default state id for {}, combinations={:?}, defaults={:?}", block_name_pascal_case.to_string(), block_properties_vec, defaults) panic!("Couldn't get default state id for {block_name_pascal_case}, combinations={block_properties_vec:?}, defaults={defaults:?}")
}; };
// 7035..=7058 => { // 7035..=7058 => {
@ -583,7 +583,7 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
block_structs.extend(block_struct); block_structs.extend(block_struct);
} }
let last_state_id = (state_id - 1) as u32; let last_state_id = state_id - 1;
let mut generated = quote! { let mut generated = quote! {
#property_enums #property_enums

View file

@ -33,7 +33,6 @@ opt-level = 1
opt-level = 3 opt-level = 3
``` ```
# Examples # Examples
```rust,no_run ```rust,no_run
@ -49,9 +48,9 @@ async fn main() {
// or Account::microsoft("example@example.com").await.unwrap(); // or Account::microsoft("example@example.com").await.unwrap();
loop { loop {
let e = azalea::ClientBuilder::new() let e = ClientBuilder::new()
.set_handler(handle) .set_handler(handle)
.start(account, "localhost") .start(account.clone(), "localhost")
.await; .await;
eprintln!("{:?}", e); eprintln!("{:?}", e);
} }
@ -72,6 +71,10 @@ async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
} }
``` ```
# 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/mat-1/azalea/blob/main/azalea/examples/testbot.rs) for an example.
# Plugins # Plugins
Azalea uses [Bevy ECS](https://docs.rs/bevy_ecs) internally to store information about the world and clients. Bevy plugins are more powerful than async handler functions, but more difficult to use. See [pathfinder](azalea/src/pathfinder/mod.rs) as an example of how to make a plugin. You can then enable a plugin by adding `.add_plugin(ExamplePlugin)` in your client/swarm builder. Azalea uses [Bevy ECS](https://docs.rs/bevy_ecs) internally to store information about the world and clients. Bevy plugins are more powerful than async handler functions, but more difficult to use. See [pathfinder](azalea/src/pathfinder/mod.rs) as an example of how to make a plugin. You can then enable a plugin by adding `.add_plugin(ExamplePlugin)` in your client/swarm builder.

View file

@ -6,7 +6,7 @@ use azalea::ecs::query::With;
use azalea::entity::metadata::Player; use azalea::entity::metadata::Player;
use azalea::entity::Position; use azalea::entity::Position;
use azalea::pathfinder::BlockPosGoal; use azalea::pathfinder::BlockPosGoal;
use azalea::{prelude::*, BlockPos, GameProfileComponent, Swarm, SwarmEvent, WalkDirection}; use azalea::{prelude::*, swarm::prelude::*, BlockPos, GameProfileComponent, WalkDirection};
use azalea::{Account, Client, Event}; use azalea::{Account, Client, Event};
use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket; use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
use std::time::Duration; use std::time::Duration;

View file

@ -4,7 +4,7 @@
mod bot; mod bot;
pub mod pathfinder; pub mod pathfinder;
pub mod prelude; pub mod prelude;
mod swarm; pub mod swarm;
pub use azalea_block as blocks; pub use azalea_block as blocks;
pub use azalea_client::*; pub use azalea_client::*;
@ -23,7 +23,6 @@ use protocol::{
resolver::{self, ResolverError}, resolver::{self, ResolverError},
ServerAddress, ServerAddress,
}; };
pub use swarm::*;
use thiserror::Error; use thiserror::Error;
use tokio::sync::mpsc; use tokio::sync::mpsc;
@ -43,10 +42,19 @@ pub enum StartError {
/// making Azalea bots. /// making Azalea bots.
/// ///
/// ```no_run /// ```no_run
/// azalea::ClientBuilder::new() /// # use azalea::prelude::*;
/// # #[tokio::main]
/// # async fn main() {
/// ClientBuilder::new()
/// .set_handler(handle) /// .set_handler(handle)
/// .start(Account::offline("bot"), "localhost") /// .start(Account::offline("bot"), "localhost")
/// .await; /// .await;
/// # }
/// # #[derive(Component, Clone, Default)]
/// # pub struct State;
/// # async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
/// # Ok(())
/// # }
/// ``` /// ```
pub struct ClientBuilder<S, Fut> pub struct ClientBuilder<S, Fut>
where where
@ -79,9 +87,20 @@ where
/// Set the function that's called every time a bot receives an [`Event`]. /// Set the function that's called every time a bot receives an [`Event`].
/// This is the way to handle normal per-bot events. /// This is the way to handle normal per-bot events.
/// ///
/// You can only have one client handler, calling this again will replace /// You must have exactly one client handler, calling this again will
/// the old client handler function (you can have a client handler and swarm /// replace the old client handler function.
/// handler separately though). ///
/// ```
/// # use azalea::prelude::*;
/// # let client_builder = azalea::ClientBuilder::new();
/// client_builder.set_handler(handle);
///
/// # #[derive(Component, Clone, Default)]
/// # pub struct State;
/// async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
/// Ok(())
/// }
/// ```
#[must_use] #[must_use]
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self { pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
self.handler = Some(handler); self.handler = Some(handler);

View file

@ -1,9 +1,6 @@
//! The Azalea prelude. Things that are necessary for a bare-bones bot are //! The Azalea prelude. Things that are necessary for a bare-bones bot are
//! re-exported here. //! re-exported here.
pub use crate::bot::BotClientExt; pub use crate::{bot::BotClientExt, pathfinder::PathfinderClientExt, ClientBuilder};
pub use crate::pathfinder::PathfinderClientExt;
pub use crate::{ClientBuilder, SwarmBuilder};
pub use azalea_client::{Account, Client, Event}; pub use azalea_client::{Account, Client, Event};
pub use azalea_ecs::component::Component; pub use azalea_ecs::{component::Component, system::Resource};
pub use azalea_ecs::system::Resource;

View file

@ -23,7 +23,7 @@ use azalea_ecs::{
}; };
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::{Swarm, SwarmEvent}; use super::{Swarm, SwarmEvent};
#[derive(Clone)] #[derive(Clone)]
pub struct SwarmChatPlugin; pub struct SwarmChatPlugin;

View file

@ -2,6 +2,7 @@
mod chat; mod chat;
mod events; mod events;
pub mod prelude;
use crate::{bot::DefaultBotPlugins, HandleFn}; use crate::{bot::DefaultBotPlugins, HandleFn};
use azalea_client::{init_ecs_app, start_ecs, Account, ChatPacket, Client, Event, JoinError}; use azalea_client::{init_ecs_app, start_ecs, Account, ChatPacket, Client, Event, JoinError};
@ -136,9 +137,30 @@ where
/// Set the function that's called every time a bot receives an [`Event`]. /// Set the function that's called every time a bot receives an [`Event`].
/// This is the way to handle normal per-bot events. /// This is the way to handle normal per-bot events.
/// ///
/// You can only have one client handler, calling this again will replace /// You must have exactly one client handler and one swarm handler, calling
/// the old client handler function (you can have a client handler and swarm /// this again will replace the old client handler function.
/// handler separately though). ///
/// ```
/// # use azalea::{prelude::*, swarm::prelude::*};
/// # let swarm_builder = SwarmBuilder::new().set_swarm_handler(swarm_handle);
/// swarm_builder.set_handler(handle);
///
/// #[derive(Component, Default, Clone)]
/// struct State {}
/// async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
/// Ok(())
/// }
///
/// # #[derive(Resource, Default, Clone)]
/// # struct SwarmState {}
/// # async fn swarm_handle(
/// # mut swarm: Swarm,
/// # event: SwarmEvent,
/// # state: SwarmState,
/// # ) -> anyhow::Result<()> {
/// # Ok(())
/// # }
/// ```
#[must_use] #[must_use]
pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self { pub fn set_handler(mut self, handler: HandleFn<Fut, S>) -> Self {
self.handler = Some(handler); self.handler = Some(handler);
@ -147,9 +169,31 @@ where
/// Set the function that's called every time the swarm receives a /// Set the function that's called every time the swarm receives a
/// [`SwarmEvent`]. This is the way to handle global swarm events. /// [`SwarmEvent`]. This is the way to handle global swarm events.
/// ///
/// You can only have one swarm handler, calling this again will replace /// You must have exactly one client handler and one swarm handler, calling
/// the old swarm handler function (you can have a client handler and swarm /// this again will replace the old swarm handler function.
/// handler separately though). ///
/// ```
/// # use azalea::{prelude::*, swarm::prelude::*};
/// # let swarm_builder = SwarmBuilder::new().set_handler(handle);
/// swarm_builder.set_swarm_handler(swarm_handle);
///
/// # #[derive(Component, Default, Clone)]
/// # struct State {}
///
/// # async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
/// # Ok(())
/// # }
///
/// #[derive(Resource, Default, Clone)]
/// struct SwarmState {}
/// async fn swarm_handle(
/// mut swarm: Swarm,
/// event: SwarmEvent,
/// state: SwarmState,
/// ) -> anyhow::Result<()> {
/// Ok(())
/// }
/// ```
#[must_use] #[must_use]
pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self { pub fn set_swarm_handler(mut self, handler: SwarmHandleFn<SwarmFut, SS>) -> Self {
self.swarm_handler = Some(handler); self.swarm_handler = Some(handler);
@ -337,7 +381,7 @@ pub enum SwarmStartError {
/// ///
/// # Examples /// # Examples
/// ```rust,no_run /// ```rust,no_run
/// use azalea::{prelude::*, Swarm, SwarmEvent}; /// use azalea::{prelude::*, swarm::prelude::*};
/// use std::time::Duration; /// use std::time::Duration;
/// ///
/// #[derive(Default, Clone, Component)] /// #[derive(Default, Clone, Component)]
@ -376,7 +420,7 @@ pub enum SwarmStartError {
/// } /// }
/// ///
/// async fn swarm_handle( /// async fn swarm_handle(
/// mut swarm: Swarm<State>, /// mut swarm: Swarm,
/// event: SwarmEvent, /// event: SwarmEvent,
/// _state: SwarmState, /// _state: SwarmState,
/// ) -> anyhow::Result<()> { /// ) -> anyhow::Result<()> {
@ -483,10 +527,15 @@ impl IntoIterator for Swarm {
/// Iterate over the bots in this swarm. /// Iterate over the bots in this swarm.
/// ///
/// ```rust,no_run /// ```rust,no_run
/// # use azalea::{prelude::*, swarm::prelude::*};
/// #[derive(Component, Clone)]
/// # pub struct State;
/// # fn example(swarm: Swarm) {
/// for bot in swarm { /// for bot in swarm {
/// let state = bot.component::<State>(); /// let state = bot.component::<State>();
/// // ... /// // ...
/// } /// }
/// # }
/// ``` /// ```
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.bots self.bots