Skip to main content

steel_core/inventory/container/
crafting.rs

1//! Crafting containers and related types.
2
3use steel_registry::{
4    item_stack::ItemStack,
5    recipe::{CraftingInput, PositionedCraftingInput},
6};
7use steel_utils::{DowncastType, DowncastTypeKey};
8
9use crate::inventory::container::Container;
10
11/// A container for crafting grid items.
12///
13/// Holds items in a crafting grid pattern (2x2 for player inventory,
14/// 3x3 for crafting table).
15pub struct CraftingContainer {
16    width: usize,
17    height: usize,
18    items: Vec<ItemStack>,
19}
20
21// SAFETY: This key is owned by Steel and uniquely identifies `CraftingContainer`.
22unsafe impl DowncastType for CraftingContainer {
23    const TYPE_KEY: DowncastTypeKey = DowncastTypeKey::new("steel:container/crafting");
24}
25
26impl CraftingContainer {
27    /// Creates a new crafting container with the given dimensions.
28    #[must_use]
29    pub fn new(width: usize, height: usize) -> Self {
30        let size = width * height;
31        Self {
32            width,
33            height,
34            items: vec![ItemStack::empty(); size],
35        }
36    }
37
38    /// Returns the width of the crafting grid.
39    #[must_use]
40    pub const fn width(&self) -> usize {
41        self.width
42    }
43
44    /// Returns the height of the crafting grid.
45    #[must_use]
46    pub const fn height(&self) -> usize {
47        self.height
48    }
49
50    /// Creates a positioned `CraftingInput` representing the current state of the grid.
51    ///
52    /// The positioned input contains a trimmed version of the grid (only the
53    /// bounding box of non-empty items) along with the offset from the original
54    /// grid origin. This is used for recipe matching and when consuming
55    /// ingredients to correctly map recipe slots back to the original crafting
56    /// grid slots.
57    #[must_use]
58    pub fn as_positioned_input(&self) -> PositionedCraftingInput {
59        CraftingInput::positioned(self.width, self.height, self.items.clone())
60    }
61
62    /// Returns a reference to the items in the grid.
63    #[must_use]
64    pub fn items(&self) -> &[ItemStack] {
65        &self.items
66    }
67}
68
69impl Container for CraftingContainer {
70    fn items(&self) -> &[ItemStack] {
71        &self.items
72    }
73
74    fn items_mut(&mut self) -> &mut [ItemStack] {
75        &mut self.items
76    }
77
78    fn set_changed(&mut self) {
79        // Crafting container doesn't track dirty state itself;
80        // the menu handles recipe recalculation on changes.
81    }
82}