aboutsummaryrefslogtreecommitdiff
path: root/azalea-inventory/azalea-inventory-macros/src/menu_enum.rs
blob: f2236ded021cda3174ddae265af34df2a75b2838 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! Generate the `enum menu` and nothing else. Implementations are in
//! impl_menu.rs

use proc_macro2::TokenStream;
use quote::quote;

use crate::parse_macro::{DeclareMenus, Field, Menu};

pub fn generate(input: &DeclareMenus) -> TokenStream {
    let mut variants = quote! {};
    let mut player_fields = None;
    for menu in &input.menus {
        if menu.name == "Player" {
            player_fields = Some(generate_fields(&menu.fields, true));
        } else {
            variants.extend(generate_variant_for_menu(menu));
        }
    }
    let player_fields = player_fields.expect("Player variant must be present");

    quote! {
        #[derive(Clone, Debug, Default)]
        pub struct Player {
            #player_fields
        }

        /// A menu, which is a fixed collection of slots.
        #[derive(Clone, Debug)]
        pub enum Menu {
            Player(Player),
            #variants
        }
    }
}

/// Player {
///     craft_result: ItemStack,
///     craft: [ItemStack; 4],
///     armor: [ItemStack; 4],
///     inventory: [ItemStack; 36],
///     offhand: ItemStack,
/// },
fn generate_variant_for_menu(menu: &Menu) -> TokenStream {
    let name = &menu.name;
    let fields = generate_fields(&menu.fields, false);

    quote! {
        #name {
            #fields
        },
    }
}

fn generate_fields(fields: &[Field], public: bool) -> TokenStream {
    let mut generated_fields = quote! {};
    for field in fields {
        let field_length = field.length;
        let field_type = if field.length == 1 {
            quote! { ItemStack }
        } else {
            quote! { SlotList<#field_length> }
        };
        let field_name = &field.name;
        if public {
            generated_fields.extend(quote! { pub #field_name: #field_type, })
        } else {
            generated_fields.extend(quote! { #field_name: #field_type, })
        }
    }
    generated_fields
}