1
2
Fork 0
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:
mat 2022-11-30 21:13:47 -06:00
parent 2f7bcd54dc
commit 8cb32d75ad
6 changed files with 125 additions and 53 deletions

View file

@ -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

View file

@ -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
}
},
}
}

View file

@ -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,
}
}
},
}
}

View file

@ -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 })
}
}

View file

@ -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,
}
} // ...
})
}
}

View 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(())
}