Skip to main content

steel_core/inventory/slots/
result_handler.rs

1use std::sync::Arc;
2
3use steel_registry::item_stack::ItemStack;
4
5use crate::{
6    inventory::lock::{ContainerLockGuard, ContainerRef},
7    player::Player,
8};
9
10/// A trait for recipe handlers that update slots in containers according to recipes
11pub trait ResultHandler: Send + Sync {
12    /// The container the result is written to and read from.
13    ///
14    /// [`ResultSlot::new`](crate::inventory::slots::ResultSlot::new) derives the
15    /// slot's container from this. Menu builders reuse that exact reference for
16    /// validation and locking, so handler writes and slot reads cannot target
17    /// different containers.
18    fn result_container(&self) -> ContainerRef;
19
20    /// Auxiliary containers accessed while validating or taking the result.
21    ///
22    /// The result container itself is already supplied by
23    /// [`result_container`](Self::result_container) and must not be repeated.
24    fn dependencies(&self) -> Vec<ContainerRef>;
25
26    /// Recalculate the result based on current inputs.
27    fn update_result(&self, guard: &mut ContainerLockGuard);
28
29    /// Consume inputs when the result is taken. Return overflow remainders.
30    fn on_result_taken(&self, guard: &mut ContainerLockGuard, player: &Player)
31    -> Option<ItemStack>;
32
33    /// Whether the stored result still matches the current inputs.
34    fn is_result_valid(&self, guard: &ContainerLockGuard, player: &Player) -> bool;
35}
36
37impl<T: ResultHandler + ?Sized> ResultHandler for Arc<T> {
38    fn result_container(&self) -> ContainerRef {
39        (**self).result_container()
40    }
41
42    fn dependencies(&self) -> Vec<ContainerRef> {
43        (**self).dependencies()
44    }
45
46    fn update_result(&self, guard: &mut ContainerLockGuard) {
47        (**self).update_result(guard);
48    }
49
50    fn on_result_taken(
51        &self,
52        guard: &mut ContainerLockGuard,
53        player: &Player,
54    ) -> Option<ItemStack> {
55        (**self).on_result_taken(guard, player)
56    }
57
58    fn is_result_valid(&self, guard: &ContainerLockGuard, player: &Player) -> bool {
59        (**self).is_result_valid(guard, player)
60    }
61}