azalea_inventory/
lib.rs

1#![doc = include_str!("../README.md")]
2#![feature(min_specialization)]
3
4pub mod components;
5pub mod default_components;
6pub mod item;
7pub mod operations;
8mod slot;
9
10use std::ops::{Deref, DerefMut, RangeInclusive};
11
12use azalea_inventory_macros::declare_menus;
13pub use slot::{DataComponentPatch, ItemStack, ItemStackData};
14
15// TODO: remove this here and in azalea-inventory-macros when rust makes
16// Default be implemented for all array sizes
17// https://github.com/rust-lang/rust/issues/61415
18
19/// A fixed-size list of [`ItemStack`]s.
20#[derive(Clone, Debug)]
21pub struct SlotList<const N: usize>([ItemStack; N]);
22impl<const N: usize> Deref for SlotList<N> {
23    type Target = [ItemStack; N];
24    fn deref(&self) -> &Self::Target {
25        &self.0
26    }
27}
28impl<const N: usize> DerefMut for SlotList<N> {
29    fn deref_mut(&mut self) -> &mut Self::Target {
30        &mut self.0
31    }
32}
33impl<const N: usize> Default for SlotList<N> {
34    fn default() -> Self {
35        SlotList([(); N].map(|_| ItemStack::Empty))
36    }
37}
38impl<const N: usize> SlotList<N> {
39    pub fn new(items: [ItemStack; N]) -> Self {
40        SlotList(items)
41    }
42}
43
44impl Menu {
45    /// Get the [`Player`] from this [`Menu`].
46    ///
47    /// # Panics
48    ///
49    /// Will panic if the menu isn't `Menu::Player`.
50    pub fn as_player(&self) -> &Player {
51        self.try_as_player()
52            .expect("Called `Menu::as_player` on a menu that wasn't `Player`.")
53    }
54    /// Get the [`Player`] from this [`Menu`], or returns `None` if the menu
55    /// isn't a player menu.
56    pub fn try_as_player(&self) -> Option<&Player> {
57        if let Menu::Player(player) = &self {
58            Some(player)
59        } else {
60            None
61        }
62    }
63
64    /// Same as [`Menu::as_player`], but returns a mutable reference to the
65    /// [`Player`].
66    ///
67    /// # Panics
68    ///
69    /// Will panic if the menu isn't `Menu::Player`.
70    pub fn as_player_mut(&mut self) -> &mut Player {
71        self.try_as_player_mut()
72            .expect("Called `Menu::as_player_mut` on a menu that wasn't `Player`.")
73    }
74    /// Same as [`Menu::try_as_player`], but returns a mutable reference to the
75    /// [`Player`].
76    pub fn try_as_player_mut(&mut self) -> Option<&mut Player> {
77        if let Menu::Player(player) = self {
78            Some(player)
79        } else {
80            None
81        }
82    }
83}
84
85// the player inventory part is always the last 36 slots (except in the Player
86// menu), so we don't have to explicitly specify it
87
88// Client {
89//     ...
90//     pub menu: Menu,
91//     pub inventory: Arc<[Slot; 36]>
92// }
93
94// Generate a `struct Player`, `enum Menu`, and `impl Menu`.
95// a "player" field gets implicitly added with the player inventory
96
97declare_menus! {
98    Player {
99        craft_result: 1,
100        craft: 4,
101        armor: 4,
102        inventory: 36,
103        offhand: 1,
104    },
105    Generic9x1 {
106        contents: 9,
107    },
108    Generic9x2 {
109        contents: 18,
110    },
111    Generic9x3 {
112        contents: 27,
113    },
114    Generic9x4 {
115        contents: 36,
116    },
117    Generic9x5 {
118        contents: 45,
119    },
120    Generic9x6 {
121        contents: 54,
122    },
123    Generic3x3 {
124        contents: 9,
125    },
126    Crafter3x3 {
127        contents: 9,
128    },
129    Anvil {
130        first: 1,
131        second: 1,
132        result: 1,
133    },
134    Beacon {
135        payment: 1,
136    },
137    BlastFurnace {
138        ingredient: 1,
139        fuel: 1,
140        result: 1,
141    },
142    BrewingStand {
143        bottles: 3,
144        ingredient: 1,
145        fuel: 1,
146    },
147    Crafting {
148        result: 1,
149        grid: 9,
150    },
151    Enchantment {
152        item: 1,
153        lapis: 1,
154    },
155    Furnace {
156        ingredient: 1,
157        fuel: 1,
158        result: 1,
159    },
160    Grindstone {
161        input: 1,
162        additional: 1,
163        result: 1,
164    },
165    Hopper {
166        contents: 5,
167    },
168    Lectern {
169        book: 1,
170    },
171    Loom {
172        banner: 1,
173        dye: 1,
174        pattern: 1,
175        result: 1,
176    },
177    Merchant {
178        payments: 2,
179        result: 1,
180    },
181    ShulkerBox {
182        contents: 27,
183    },
184    Smithing {
185        template: 1,
186        base: 1,
187        additional: 1,
188        result: 1,
189    },
190    Smoker {
191        ingredient: 1,
192        fuel: 1,
193        result: 1,
194    },
195    CartographyTable {
196        map: 1,
197        additional: 1,
198        result: 1,
199    },
200    Stonecutter {
201        input: 1,
202        result: 1,
203    },
204}