mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
inventory macro works
This commit is contained in:
parent
2f7bcd54dc
commit
8cb32d75ad
6 changed files with 125 additions and 53 deletions
|
@ -10,13 +10,13 @@ use syn::{self, parse_macro_input, Ident};
|
|||
|
||||
#[proc_macro]
|
||||
pub fn declare_menus(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeclareMenus);
|
||||
let mut input = parse_macro_input!(input as DeclareMenus);
|
||||
|
||||
// implicitly add a `player` field at the end unless an `inventory` field
|
||||
// is present
|
||||
for menu in &mut input.menus {
|
||||
let mut inventory_field_missing = true;
|
||||
for field in menu.fields {
|
||||
for field in &menu.fields {
|
||||
if matches!(field.name.to_string().as_str(), "inventory" | "player") {
|
||||
inventory_field_missing = false;
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ pub fn declare_menus(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
let menu_enum = menu_enum::generate(input);
|
||||
let menu_impl = menu_impl::generate(input);
|
||||
let menu_enum = menu_enum::generate(&input);
|
||||
let menu_impl = menu_impl::generate(&input);
|
||||
|
||||
quote! {
|
||||
#menu_enum
|
||||
|
|
|
@ -5,15 +5,15 @@ use crate::parse_macro::{DeclareMenus, Menu};
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub fn generate(input: DeclareMenus) -> TokenStream {
|
||||
let mut variants = Vec::new();
|
||||
for menu in input.menus {
|
||||
variants.push(generate_variant_for_menu(menu));
|
||||
pub fn generate(input: &DeclareMenus) -> TokenStream {
|
||||
let mut variants = quote! {};
|
||||
for menu in &input.menus {
|
||||
variants.extend(generate_variant_for_menu(menu));
|
||||
}
|
||||
|
||||
quote! {
|
||||
pub enum Menu {
|
||||
#(#variants),*
|
||||
#variants
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ pub fn generate(input: DeclareMenus) -> TokenStream {
|
|||
/// inventory: [Slot; 36],
|
||||
/// offhand: Slot,
|
||||
/// },
|
||||
fn generate_variant_for_menu(menu: Menu) -> TokenStream {
|
||||
let name = menu.name;
|
||||
fn generate_variant_for_menu(menu: &Menu) -> TokenStream {
|
||||
let name = &menu.name;
|
||||
let mut fields = quote! {};
|
||||
|
||||
for field in menu.fields {
|
||||
let field_name = field.name;
|
||||
for field in &menu.fields {
|
||||
let field_name = &field.name;
|
||||
|
||||
let field_length = field.length;
|
||||
let field_type = if matches!(field_name.to_string().as_str(), "inventory" | "player") {
|
||||
|
@ -46,6 +46,6 @@ fn generate_variant_for_menu(menu: Menu) -> TokenStream {
|
|||
quote! {
|
||||
#name {
|
||||
#fields
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ use crate::parse_macro::{DeclareMenus, Menu};
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
pub fn generate(input: DeclareMenus) -> TokenStream {
|
||||
pub fn generate(input: &DeclareMenus) -> TokenStream {
|
||||
let mut match_variants = quote! {};
|
||||
for menu in input.menus {
|
||||
for menu in &input.menus {
|
||||
match_variants.extend(generate_match_variant_for_menu(menu));
|
||||
}
|
||||
|
||||
|
@ -37,17 +37,38 @@ pub fn generate(input: DeclareMenus) -> TokenStream {
|
|||
/// _ => return None,
|
||||
/// }
|
||||
/// } // ...
|
||||
pub fn generate_match_variant_for_menu(menu: Menu) -> TokenStream {
|
||||
let menu_name = menu.name;
|
||||
let menu_field_names = menu.fields.into_iter().map(|f| f.name);
|
||||
pub fn generate_match_variant_for_menu(menu: &Menu) -> TokenStream {
|
||||
let menu_name = &menu.name;
|
||||
let mut menu_field_names = quote! {};
|
||||
for field in &menu.fields {
|
||||
let field_name = &field.name;
|
||||
menu_field_names.extend(quote! { #field_name, })
|
||||
}
|
||||
|
||||
let mut match_arms = quote! {};
|
||||
let mut i = 0;
|
||||
for field in &menu.fields {
|
||||
let field_name = &field.name;
|
||||
let start = i;
|
||||
i += field.length;
|
||||
let end = i - 1;
|
||||
match_arms.extend(if start == end {
|
||||
quote! { #start => #field_name, }
|
||||
} else if start == 0 {
|
||||
quote! { #start..=#end => &#field_name[i], }
|
||||
} else {
|
||||
quote! { #start..=#end => &#field_name[i - #start], }
|
||||
});
|
||||
}
|
||||
|
||||
quote! {
|
||||
Menu::#menu_name {
|
||||
#(#menu_field_names),*
|
||||
#menu_field_names
|
||||
} => {
|
||||
match i {
|
||||
#match_arms
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@ impl Parse for Menu {
|
|||
.into_iter()
|
||||
.collect();
|
||||
|
||||
input.parse::<Token![,]>()?;
|
||||
Ok(Self { name, fields })
|
||||
}
|
||||
}
|
||||
|
@ -60,14 +59,10 @@ pub struct DeclareMenus {
|
|||
}
|
||||
impl Parse for DeclareMenus {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let menus = content
|
||||
let menus = input
|
||||
.parse_terminated::<Menu, Token![,]>(Menu::parse)?
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
input.parse::<Token![,]>()?;
|
||||
Ok(Self { menus })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use azalea_inventory_macros::declare_menus;
|
|||
// Generate an `enum Menu` and `impl Menu`.
|
||||
// if the `inventory` field is present, then the `player` field doesn't get
|
||||
// implicitly added
|
||||
declare_menus!({
|
||||
declare_menus! {
|
||||
Player {
|
||||
craft_result: 1,
|
||||
craft: 4,
|
||||
|
@ -33,29 +33,4 @@ declare_menus!({
|
|||
Chest {
|
||||
block: 27,
|
||||
}
|
||||
});
|
||||
|
||||
impl Menu {
|
||||
/// Get a mutable reference to the [`Slot`] at the given protocol index. If
|
||||
/// you're trying to get an item in a menu normally, you should just
|
||||
/// `match` it and index the `[Slot]` you get
|
||||
pub fn slot_mut(&self, i: usize) -> Option<&Slot> {
|
||||
Some(match self {
|
||||
Menu::Player {
|
||||
craft_result,
|
||||
craft,
|
||||
armor,
|
||||
inventory,
|
||||
offhand,
|
||||
} => {
|
||||
match i {
|
||||
0 => craft_result,
|
||||
1..=4 => craft,
|
||||
5..=8 => armor,
|
||||
// ...
|
||||
_ => return None,
|
||||
}
|
||||
} // ...
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
81
azalea/examples/inventory_art.rs
Normal file
81
azalea/examples/inventory_art.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
//! Take wool from a chest and put one random piece of wool in every inventory slot
|
||||
|
||||
use azalea::prelude::*;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let account = Account::offline("bot");
|
||||
// or let bot = Account::microsoft("email").await;
|
||||
|
||||
azalea::start(azalea::Options {
|
||||
account,
|
||||
address: "localhost",
|
||||
state: State::default(),
|
||||
plugins: plugins![],
|
||||
handle,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct State {
|
||||
pub started: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
||||
async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||
match event {
|
||||
Event::Chat(m) => {
|
||||
if m.username() == Some(bot.profile.name) {
|
||||
return Ok(());
|
||||
};
|
||||
if m.content() != "go" {
|
||||
return Ok(());
|
||||
}
|
||||
{
|
||||
// make sure we only start once
|
||||
if *state.started.lock() {
|
||||
return Ok(());
|
||||
};
|
||||
*state.started.lock() = true;
|
||||
}
|
||||
|
||||
let chest_block = bot.world().find_one_block(|b| b.id == "minecraft:chest");
|
||||
bot.goto(chest_block).await;
|
||||
let chest = bot
|
||||
.open_container(&bot.world().find_one_block(|b| b.id == "minecraft:chest"))
|
||||
.await
|
||||
.unwrap();
|
||||
bot.take_amount_from_container(&chest, 5, |i| i.id == "#minecraft:planks")
|
||||
.await;
|
||||
chest.close().await;
|
||||
|
||||
let crafting_table = bot
|
||||
.open_crafting_table(
|
||||
&bot.world
|
||||
.find_one_block(|b| b.id == "minecraft:crafting_table"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
bot.craft(&crafting_table, &bot.recipe_for("minecraft:sticks"))
|
||||
.await?;
|
||||
let pickaxe = bot
|
||||
.craft(&crafting_table, &bot.recipe_for("minecraft:wooden_pickaxe"))
|
||||
.await?;
|
||||
crafting_table.close().await;
|
||||
|
||||
bot.hold(&pickaxe);
|
||||
loop {
|
||||
if let Err(e) = bot.dig(bot.entity().feet_pos().down(1)).await {
|
||||
println!("{:?}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Reference in a new issue