mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
parent
37f9f1c6fe
commit
06068377bd
11 changed files with 163 additions and 26 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -101,6 +101,11 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||
[[package]]
|
||||
name = "azalea"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"env_logger",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azalea-auth"
|
||||
|
@ -890,9 +895,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
|
||||
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
|
@ -1432,10 +1437,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.19.2"
|
||||
version = "1.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
|
||||
checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
|
|
|
@ -66,7 +66,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_from_blockstate() {
|
||||
let box_block: Box<dyn Block> = Box::<dyn Block>::from(BlockState::Air);
|
||||
assert_eq!(box_block.id(), "air");
|
||||
let block: Box<dyn Block> = Box::<dyn Block>::from(BlockState::Air);
|
||||
assert_eq!(block.id(), "air");
|
||||
|
||||
let block: Box<dyn Block> = Box::<dyn Block>::from(BlockState::FloweringAzalea);
|
||||
assert_eq!(block.id(), "flowering_azalea");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,3 +9,9 @@ version = "0.1.0"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = "^1.21.1"
|
||||
env_logger = "^0.9.1"
|
||||
anyhow = "^1.0.65"
|
||||
|
|
|
@ -30,12 +30,11 @@ async fn handle_event(event: &Event, bot: &Bot, ctx: Arc<Context>) {
|
|||
ctx_lock.started = true;
|
||||
drop(ctx_lock);
|
||||
|
||||
bot.goto_goal(
|
||||
bot.goto(
|
||||
pathfinder::Goals::NearXZ(5, azalea::BlockXZ(0, 0))
|
||||
).await;
|
||||
let chest = bot.open_container(&bot.world.find_one_block(|b| b.id == "minecraft:chest")).await.unwrap();
|
||||
bot.take_amount(&chest, 5, |i| i.id == "#minecraft:planks").await;
|
||||
// when rust adds async drop this won't be necessary
|
||||
chest.close().await;
|
||||
|
||||
let crafting_table = bot.open_crafting_table(&bot.world.find_one_block(|b| b.id == "minecraft:crafting_table")).await.unwrap();
|
|
@ -12,15 +12,15 @@ async fn main() {
|
|||
|
||||
let bots = accounts.join("localhost".try_into().unwrap()).await.unwrap();
|
||||
|
||||
bots.goto(azalea::BlockCoord(0, 70, 0)).await;
|
||||
// or bots.goto_goal(pathfinder::Goals::Goto(azalea::BlockCoord(0, 70, 0))).await;
|
||||
bots.goto(azalea::BlockPos::new(0, 70, 0)).await;
|
||||
// or bots.goto_goal(pathfinder::Goals::Goto(azalea::BlockPos(0, 70, 0))).await;
|
||||
|
||||
// destroy the blocks in this area and then leave
|
||||
|
||||
bots.fill(
|
||||
azalea::Selection::Range(
|
||||
azalea::BlockCoord(0, 0, 0),
|
||||
azalea::BlockCoord(16, 255, 16)
|
||||
azalea::BlockPos::new(0, 0, 0),
|
||||
azalea::BlockPos::new(16, 255, 16)
|
||||
),
|
||||
azalea::block::Air
|
||||
).await;
|
24
azalea/examples/potatobot/README.md
Normal file
24
azalea/examples/potatobot/README.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
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
|
20
azalea/examples/potatobot/autoeat.rs
Normal file
20
azalea/examples/potatobot/autoeat.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
//! Automatically eat when we get hungry.
|
||||
|
||||
use azalea::{Client, Event};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct State {}
|
||||
|
||||
pub async fn handle(bot: &mut Client, event: Event, state: Arc<Mutex<State>>) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
91
azalea/examples/potatobot/main.rs
Normal file
91
azalea/examples/potatobot/main.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
mod autoeat;
|
||||
|
||||
use azalea::{pathfinder, Account, BlockPos, Client, Event, ItemKind, MoveDirection, Vec3};
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct State {
|
||||
pub eating: bool,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let account = Account::offline("bot");
|
||||
let (bot, mut rx) = account
|
||||
.join(&"localhost".try_into().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Maybe all this could be turned into a macro in the future?
|
||||
let state = Arc::new(Mutex::new(State::default()));
|
||||
let autoeat_state = Arc::new(Mutex::new(autoeat::State::default()));
|
||||
let pathfinder_state = Arc::new(Mutex::new(pathfinder::State::default()));
|
||||
while let Some(event) = rx.recv().await {
|
||||
// we put it into an Arc so it's cheaper to clone
|
||||
let event = Arc::new(event);
|
||||
|
||||
tokio::spawn(autoeat::handle(
|
||||
bot.clone(),
|
||||
event.clone(),
|
||||
autoeat_state.clone(),
|
||||
));
|
||||
tokio::spawn(pathfinder::handle(
|
||||
bot.clone(),
|
||||
event.clone(),
|
||||
pathfinder_state.clone(),
|
||||
));
|
||||
tokio::spawn(handle(bot.clone(), event.clone(), state.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(bot: Client, event: Event, state: Arc<Mutex<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: Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||
bot.state
|
||||
.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: &mut Arc<Mutex<State>>) -> anyhow::Result<()> {
|
||||
// first throw away any garbage we might have
|
||||
bot.toss(|item| item.kind != ItemKind::Potato && item.kind != ItemKind::DiamondHoe);
|
||||
|
||||
bot.state.goto(Vec3::new(0, 70, 0)).await?;
|
||||
let chest = bot
|
||||
.open_container(&bot.dimension.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,14 +1,2 @@
|
|||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
//! This is currently an advertisement crate for
|
||||
//! [Azalea](https://github.com/mat-1/azalea). More stuff will be here soon!
|
||||
|
|
Loading…
Reference in a new issue