Skip to main content

basalt_api/components/
crafting.rs

1//! Crafting grid component for player crafting state.
2
3use basalt_types::Slot;
4
5use crate::components::Component;
6
7/// Tracks the contents of a player's crafting grid.
8///
9/// Used for both the 2x2 inventory crafting grid and the 3x3 crafting
10/// table grid. The `grid_size` field determines which slots are active:
11/// for a 2x2 grid, only `slots[0..4]` are used; for a 3x3 grid, all
12/// nine slots are active.
13///
14/// The `output` slot holds the result computed by the recipe matching
15/// system. It is read-only from the player's perspective — the server
16/// sets it when the grid contents change.
17#[derive(Debug, Clone)]
18pub struct CraftingGrid {
19    /// The 9 crafting input slots. For a 2x2 grid, only indices 0-3
20    /// are used; indices 4-8 remain empty.
21    pub slots: [Slot; 9],
22    /// Grid dimension: 2 for the player inventory grid, 3 for a
23    /// crafting table.
24    pub grid_size: u8,
25    /// The crafting output slot, set by the recipe matching system.
26    pub output: Slot,
27}
28
29impl CraftingGrid {
30    /// Creates an empty 2x2 crafting grid with no items.
31    ///
32    /// All nine slot positions are initialized to empty, and the output
33    /// slot is empty. This is the default state for a player who has
34    /// not interacted with any crafting interface.
35    pub fn empty() -> Self {
36        Self {
37            slots: std::array::from_fn(|_| Slot::empty()),
38            grid_size: 2,
39            output: Slot::empty(),
40        }
41    }
42
43    /// Clears all input slots and the output slot.
44    ///
45    /// The grid size is preserved — a 3x3 grid remains 3x3 after
46    /// clearing. This is used when a player closes a crafting table
47    /// window (items are returned to inventory, grid is reset).
48    pub fn clear(&mut self) {
49        for slot in &mut self.slots {
50            *slot = Slot::empty();
51        }
52        self.output = Slot::empty();
53    }
54}
55
56impl Component for CraftingGrid {}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn empty_returns_grid_size_two() {
64        let grid = CraftingGrid::empty();
65        assert_eq!(grid.grid_size, 2);
66    }
67
68    #[test]
69    fn empty_has_all_empty_slots() {
70        let grid = CraftingGrid::empty();
71        for slot in &grid.slots {
72            assert!(slot.is_empty());
73        }
74        assert!(grid.output.is_empty());
75    }
76
77    #[test]
78    fn clear_resets_slots_but_keeps_grid_size() {
79        let mut grid = CraftingGrid::empty();
80        grid.grid_size = 3;
81        grid.slots[0] = Slot::new(1, 1);
82        grid.slots[4] = Slot::new(2, 5);
83        grid.output = Slot::new(3, 1);
84
85        grid.clear();
86
87        assert_eq!(grid.grid_size, 3);
88        for slot in &grid.slots {
89            assert!(slot.is_empty());
90        }
91        assert!(grid.output.is_empty());
92    }
93}