steel_core/inventory/menu/kinds/
crafting_menu.rs1use std::sync::Arc;
10
11use crate::inventory::container::{CraftingContainer, ResultContainer};
12use crate::inventory::prelude::*;
13use crate::inventory::slots::CraftingHandler;
14use crate::player::player_inventory::PlayerInventory;
15use steel_registry::item_stack::ItemStack;
16use steel_registry::vanilla_blocks;
17use steel_registry::vanilla_menu_types;
18use steel_utils::BlockPos;
19use steel_utils::locks::IntoShared;
20use steel_utils::locks::Shared;
21
22#[must_use]
24pub fn crafting(inventory: Shared<PlayerInventory>, container_id: u8, block_pos: BlockPos) -> Menu {
25 let crafting_container = CraftingContainer::new(3, 3).into_shared();
26 let result_container = ResultContainer::new().into_shared();
27
28 let handler = CraftingHandler::new(
29 Arc::clone(&crafting_container),
30 Arc::clone(&result_container),
31 3,
32 );
33
34 let mut builder = MenuBuilder::new(&vanilla_menu_types::CRAFTING, container_id);
35 let result = builder.crafting_result_slot(handler.clone());
36 let grid = builder.section_all(crafting_container);
37 let player = builder.player_inventory(&inventory);
38
39 builder.route(result, player.all(), FillDirection::Backward);
40 builder.route(grid, player.all(), FillDirection::Forward);
41 builder.route(
42 player.main(),
43 [grid, player.hotbar()],
44 FillDirection::Forward,
45 );
46 builder.route(
47 player.hotbar(),
48 [grid, player.main()],
49 FillDirection::Forward,
50 );
51 builder.drain(grid);
52
53 builder.build(CraftingKind {
54 result_container,
55 result,
56 block_pos,
57 handler,
58 })
59}
60
61pub struct CraftingKind {
63 result_container: Shared<ResultContainer>,
65 result: Section,
67 block_pos: BlockPos,
69 handler: CraftingHandler,
70}
71
72unsafe impl steel_utils::DowncastType for CraftingKind {
75 const TYPE_KEY: steel_utils::DowncastTypeKey =
76 steel_utils::DowncastTypeKey::new("steel:menu/crafting");
77}
78
79impl MenuKind for CraftingKind {
80 fn can_take_item_for_pick_all(&self, _carried: &ItemStack, slot_index: usize) -> bool {
82 !self.result.contains(slot_index)
83 }
84
85 fn still_valid(&self, _behavior: &MenuBehavior, player: &Player) -> bool {
86 still_valid_block(
87 &player.get_world(),
88 self.block_pos,
89 &vanilla_blocks::CRAFTING_TABLE,
90 player,
91 )
92 }
93
94 fn removed(&mut self, _behavior: &mut MenuBehavior, _player: &Player) {
96 self.result_container.lock().set_item(0, ItemStack::empty());
97 }
98
99 fn slots_changed(
100 &mut self,
101 _behavior: &mut MenuBehavior,
102 guard: &mut ContainerLockGuard,
103 _player: &Player,
104 ) {
105 self.handler.update_result(guard);
106 }
107}
108
109#[cfg(test)]
110mod tests;