mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
improve docs a bit more and delete potatobot example
This commit is contained in:
parent
f5ae1b9717
commit
758372f938
8 changed files with 12 additions and 133 deletions
|
@ -73,7 +73,7 @@ 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.
|
||||
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. Also, if you're using swarms, you should also have both `azalea::prelude::*` and `azalea::swarm::prelude::*`.
|
||||
|
||||
# Plugins
|
||||
|
||||
|
@ -83,4 +83,4 @@ Also note that just because something is an entity in the ECS doesn't mean that
|
|||
|
||||
See the [Bevy Cheatbook](https://bevy-cheatbook.github.io/programming/ecs-intro.html) to learn more about Bevy ECS (and the ECS paradigm in general).
|
||||
|
||||
[`azalea_client`]: https://docs.rs/azalea-client
|
||||
[`azalea_client`]: https://docs.rs/azalea-client
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use azalea::prelude::*;
|
||||
use azalea::{prelude::*, swarm::prelude::*};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
@ -10,7 +10,7 @@ async fn main() {
|
|||
states.push(State::default());
|
||||
}
|
||||
|
||||
let e = azalea::SwarmBuilder::new()
|
||||
let e = SwarmBuilder::new()
|
||||
.add_accounts(accounts.clone())
|
||||
.set_handler(handle)
|
||||
.set_swarm_handler(swarm_handle)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
A relatively complex bot for farming potatoes.
|
||||
|
||||
Note: At the moment, all of the code here is only hypothetical. I decided to write this to help me decide how I want some the APIs to look.
|
||||
|
||||
## Attempted
|
||||
- Sync: a sync function is called with the state and bot every time we get an event, and the function can queue events to execute at the end of the tick
|
||||
|
||||
Pros: No .lock().unwrap() necessary, and theoretically pausable by saving the state.
|
||||
|
||||
Cons: Async functions like opening containers and pathfinding are annoying because you have to keep state for them, and the code generally ends up being more confusing.
|
||||
|
||||
- Async non-blocking: an async function is called in a new task with the state mutex and bot every time we get an event
|
||||
|
||||
Pros: Easier to do async stuff like interacting with containers, code is somewhat easier to understand
|
||||
|
||||
Cons: Lock spam everywhere is annoying, and you have to make sure stuff doesn't accidentally run in parallel.
|
||||
|
||||
## Considered:
|
||||
(I didn't actually try this because the problems were apparent)
|
||||
- Async blocking: an async function is called with the state and bot every time we get an event, and only handles the next event when this one finishes running
|
||||
|
||||
Pros: No lock spam
|
||||
|
||||
Cons: Sometimes you want to handle multiple events at once like eating if you get hungry while pathfinding, this makes it harder without increasing complexity
|
|
@ -1,31 +0,0 @@
|
|||
//! Automatically eat when we get hungry.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use azalea::prelude::*;
|
||||
use azalea::{Client, Event};
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Plugin {
|
||||
pub state: State,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Component)]
|
||||
pub struct State {}
|
||||
|
||||
#[async_trait]
|
||||
impl azalea::PluginState for Plugin {
|
||||
async fn handle(self: Box<Self>, event: Event, bot: Client) {
|
||||
match event {
|
||||
Event::UpdateHunger => {
|
||||
if !bot.using_held_item() && bot.food_level() <= 17 {
|
||||
if bot.hold(azalea::ItemGroup::Food).await {
|
||||
bot.use_held_item().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
mod autoeat;
|
||||
use azalea::prelude::*;
|
||||
use azalea::{pathfinder, BlockPos, ItemKind, Vec3};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct State {}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let account = Account::offline("bot");
|
||||
|
||||
azalea::start(azalea::Options {
|
||||
account,
|
||||
address: "localhost",
|
||||
state: State::default(),
|
||||
plugins: plugins![autoeat::Plugin, pathfinder::Plugin],
|
||||
handle,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||
match event {
|
||||
Event::Login => {
|
||||
goto_farm(bot, state).await?;
|
||||
// after we get to the farm, start farming
|
||||
farm(bot, state).await?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// go to the place where we start farming
|
||||
async fn goto_farm(bot: Client, state: State) -> anyhow::Result<()> {
|
||||
bot.goto(pathfinder::Goals::Near(5, BlockPos::new(0, 70, 0)))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// go to the chest and deposit everything in our inventory.
|
||||
async fn deposit(bot: &mut Client, state: State) -> anyhow::Result<()> {
|
||||
// first throw away any garbage we might have
|
||||
bot.toss(|item| item.kind != ItemKind::Potato && item.kind != ItemKind::DiamondHoe);
|
||||
|
||||
bot.goto(Vec3::new(0, 70, 0)).await?;
|
||||
let chest = bot
|
||||
.open_container(&bot.world.block_at(BlockPos::new(0, 70, 0)))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let inventory_potato_count: usize = bot
|
||||
.inventory()
|
||||
.count_total(|item| item.kind == ItemKind::Potato);
|
||||
if inventory_potato_count > 64 {
|
||||
chest
|
||||
.deposit_total_count(
|
||||
|item| item.kind == azalea::ItemKind::Potato,
|
||||
inventory_potato_count - 64,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
chest.close().await;
|
||||
Ok(())
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use azalea::entity::metadata::Player;
|
||||
use azalea::{pathfinder, Account, Client, Event, GameProfileComponent, SwarmEvent};
|
||||
use azalea::{prelude::*, Swarm};
|
||||
use azalea::{pathfinder, Account, Client, Event, GameProfileComponent};
|
||||
use azalea::{prelude::*, swarm::prelude::*};
|
||||
use azalea_ecs::query::With;
|
||||
|
||||
#[tokio::main]
|
||||
|
@ -25,10 +25,10 @@ async fn main() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Component, Default, Clone)]
|
||||
struct State {}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Resource, Default, Clone)]
|
||||
struct SwarmState {}
|
||||
|
||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||
|
|
|
@ -29,7 +29,7 @@ use tokio::sync::mpsc;
|
|||
/// A swarm is a way to conveniently control many bots at once, while also
|
||||
/// being able to control bots at an individual level when desired.
|
||||
///
|
||||
/// Swarms are created from [`azalea::SwarmBuilder`].
|
||||
/// Swarms are created from [`azalea::swarm::SwarmBuilder`].
|
||||
///
|
||||
/// The `S` type parameter is the type of the state for individual bots.
|
||||
/// It's used to make the [`Swarm::add`] function work.
|
||||
|
|
3
azalea/src/swarm/prelude.rs
Normal file
3
azalea/src/swarm/prelude.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
//! A prelude that re-exports common swarm types in Azalea.
|
||||
|
||||
pub use crate::swarm::{Swarm, SwarmBuilder, SwarmEvent};
|
Loading…
Reference in a new issue