pub struct MenuBuilder {
instance: MenuInstanceId,
menu_type: Option<MenuTypeRef>,
container_id: u8,
overrides_player_slots: bool,
slots: Vec<Box<dyn Slot>>,
container_refs: Vec<ContainerRef>,
data_slots: Vec<i16>,
routes: Vec<Route>,
drain_sections: Vec<Range<usize>>,
claimed: Vec<(ContainerId, Range<usize>)>,
}Expand description
Builds a Menu.
See the module documentation for an overview.
Fields§
§instance: MenuInstanceId§container_id: u8§overrides_player_slots: bool§slots: Vec<Box<dyn Slot>>§container_refs: Vec<ContainerRef>§data_slots: Vec<i16>§routes: Vec<Route>§drain_sections: Vec<Range<usize>>§claimed: Vec<(ContainerId, Range<usize>)>Container-local slot ranges already covered by a section, used to catch two sections mapping onto the same container slots.
Implementations§
Source§impl MenuBuilder
impl MenuBuilder
Sourcepub fn new(menu_type: impl Into<Option<MenuTypeRef>>, container_id: u8) -> Self
pub fn new(menu_type: impl Into<Option<MenuTypeRef>>, container_id: u8) -> Self
Creates a new builder for a menu of the given type and container id.
Pass None for the player’s own inventory menu, or a menu type
(&vanilla_menu_types::ANVIL, …).
Sourcepub fn split(&mut self, container: impl Into<ContainerRef>) -> ContainerSlots
pub fn split(&mut self, container: impl Into<ContainerRef>) -> ContainerSlots
Starts splitting a Container into multiple sections.
Use this when you are locked to storing items in one Container
and need to split them into different Sections.
§Example
use steel_core::inventory::prelude::*;
use steel_core::inventory::menu::kinds::BasicKind;
let mut b = MenuBuilder::new(None, 0);
let mut stand = b.split(SimpleContainer::new(5).into_shared());
let bottles = b.section(&mut stand, 3); // slots 0..3
let ingredient = b.section(&mut stand, 1); // slot 3
let fuel = b.section(&mut stand, 1); // slot 4
b.build(BasicKind);§Panics
Panics if the sections carved from the returned handle take more slots than the container has.
Sourcefn container_size(container: &ContainerRef) -> usize
fn container_size(container: &ContainerRef) -> usize
The container’s size, read under a short lock.
Sourcepub fn section(&mut self, source: impl SectionSource, count: usize) -> Section
pub fn section(&mut self, source: impl SectionSource, count: usize) -> Section
Adds count plain slots backed by source.
Pass a container directly to cover its slots 0..count, or a
ContainerSlots handle from MenuBuilder::split to cover the next
count slots of a container shared between several sections.
Returns a Section handle over the slots that were added.
§Panics
Panics if the covered container slots overlap another section of this menu.
Sourcepub fn section_with(
&mut self,
source: impl SectionSource,
count: usize,
kind: impl Into<SectionKind>,
) -> Section
pub fn section_with( &mut self, source: impl SectionSource, count: usize, kind: impl Into<SectionKind>, ) -> Section
Adds count slots backed by source, lowered through kind.
§Example
use steel_registry::vanilla_items;
use steel_core::inventory::prelude::*;
use steel_core::inventory::menu::kinds::BasicKind;
let mut b = MenuBuilder::new(None, 0);
let container = SimpleContainer::new(9).into_shared();
let fuel = b.section_with(container, 9, SectionKind::restricted(|_slot, stack| {
stack.is(&vanilla_items::COAL)
}));
b.build(BasicKind);§Panics
Panics if the covered container slots overlap another section of this menu.
Sourcepub fn section_all(&mut self, container: impl Into<ContainerRef>) -> Section
pub fn section_all(&mut self, container: impl Into<ContainerRef>) -> Section
Sourcepub fn section_all_with(
&mut self,
container: impl Into<ContainerRef>,
kind: impl Into<SectionKind>,
) -> Section
pub fn section_all_with( &mut self, container: impl Into<ContainerRef>, kind: impl Into<SectionKind>, ) -> Section
Like section_all, but lowered through kind.
§Panics
Panics if the covered container slots overlap another section of this menu.
Sourcepub fn section_at(
&mut self,
container: impl Into<ContainerRef>,
indices: impl IntoIterator<Item = usize>,
kind: impl Into<SectionKind>,
) -> Section
pub fn section_at( &mut self, container: impl Into<ContainerRef>, indices: impl IntoIterator<Item = usize>, kind: impl Into<SectionKind>, ) -> Section
Adds slots over explicit container indices, in the given order.
The indices may be non-contiguous and in any order; each menu slot maps
to the next index of the iterator. Like section_with,
the covered indices are claimed against overlapping sections.
§Panics
Panics if an index repeats or the covered container slots overlap another section of this menu.
Sourcepub fn player_inventory(
&mut self,
inventory: &Shared<PlayerInventory>,
) -> PlayerInventorySections
pub fn player_inventory( &mut self, inventory: &Shared<PlayerInventory>, ) -> PlayerInventorySections
Adds the player’s 36 inventory slots (main inventory then hotbar).
Sourcepub fn player_inventory_with(
&mut self,
inventory: &Shared<PlayerInventory>,
kind: impl Into<SectionKind>,
) -> PlayerInventorySections
pub fn player_inventory_with( &mut self, inventory: &Shared<PlayerInventory>, kind: impl Into<SectionKind>, ) -> PlayerInventorySections
Like player_inventory, but lowers the slots
through kind, e.g. SectionKind::Display for a read-only view of
another player’s inventory.
Player inventory sections never claim their container slots: menus like invsee legitimately map the same inventory into two sections, and quick-move skips aliased slots at runtime.
Sourcepub fn result_slot(&mut self, handler: impl ResultHandler + 'static) -> Section
pub fn result_slot(&mut self, handler: impl ResultHandler + 'static) -> Section
Adds a single fake result slot driven by handler, backed by the
handler’s result_container.
See crate::inventory::container::ResultContainer and crate::inventory::slots::ResultHandler.
§Panics
Panics if the result container has no slot 0, or that slot is already
covered by another section of this menu.
Sourcepub fn data_slot(&mut self, initial: i16) -> DataSlot
pub fn data_slot(&mut self, initial: i16) -> DataSlot
Adds a data slot with an initial value and returns a typed handle to it.
Sourcepub fn route(
&mut self,
from: impl IntoSections,
targets: impl IntoSections,
direction: FillDirection,
) -> &mut Self
pub fn route( &mut self, from: impl IntoSections, targets: impl IntoSections, direction: FillDirection, ) -> &mut Self
Declares a shift-click route from each section of from into
targets.
Both arguments accept anything IntoSections: pass a single
Section directly and use an array/slice/Vec only when there is
genuinely more than one, so brackets signal arity. A multi-section
from declares one route per source section.
Most commonly:
player_inventory -> container is FillDirection::Forward
container -> player_inventory is FillDirection::Backward
§Panics
Panics if a section belongs to another builder, a source overlaps an existing route, or a target overlaps its source.
Sourcepub fn route_with_remainder_policy(
&mut self,
from: impl IntoSections,
targets: impl IntoSections,
direction: FillDirection,
fake_result_remainder: FakeResultRemainderPolicy,
) -> &mut Self
pub fn route_with_remainder_policy( &mut self, from: impl IntoSections, targets: impl IntoSections, direction: FillDirection, fake_result_remainder: FakeResultRemainderPolicy, ) -> &mut Self
Declares a shift-click route with an explicit fake-result remainder policy. The policy has no effect on ordinary source slots.
§Panics
Panics if a section belongs to another builder, a source overlaps an existing route, or a target overlaps its source.
Sourcepub fn drain(&mut self, sections: impl IntoSections) -> &mut Self
pub fn drain(&mut self, sections: impl IntoSections) -> &mut Self
Marks sections to be emptied back into the player or dropped on the floor on close.
Accepts anything IntoSections: pass a single Section directly
and use an array only for genuinely multiple sections.
§Panics
Panics if any section was created by a different MenuBuilder.
§Example
use std::sync::Arc;
use steel_registry::{item_stack::ItemStack, vanilla_items};
use steel_utils::locks::SyncMutex;
use steel_core::inventory::prelude::*;
use steel_core::inventory::menu::kinds::BasicKind;
use steel_core::inventory::container::SimpleContainer;
let container_id = 0;
let mut b = MenuBuilder::new(None, container_id);
let items = vec![ItemStack::empty(); 9];
let upper_container = SimpleContainer::from_items(items).into_shared();
let items = vec![ItemStack::new(&vanilla_items::BARRIER); 9];
let lower_container = SimpleContainer::from_items(items).into_shared();
let display = b.section_with(lower_container, 9, SectionKind::Display);
let section = b.section(upper_container, 9);
b.drain(section); // only 'section' gets drained when the menu is closed
b.build(BasicKind);Sourcepub const fn override_player_slots(&mut self) -> &mut Self
pub const fn override_player_slots(&mut self) -> &mut Self
Declares that this menu paints over the client’s standard 36 player slots.
Pending logical inventory updates are deferred while the menu is open and the slots are restored when it closes.
Sourcepub fn build_boxed(self, kind: Box<dyn MenuKind>) -> Menu
pub fn build_boxed(self, kind: Box<dyn MenuKind>) -> Menu
Consumes the builder using menu behavior selected at runtime.
This is the erased counterpart to Self::build for plugin factories
and other callers that already own a boxed menu kind.
§Panics
Panics if the number of slots does not match the client layout declared by the menu type, or if a fake slot aliases another physical slot.
Sourcefn assert_no_fake_slot_aliases(slots: &[Box<dyn Slot>])
fn assert_no_fake_slot_aliases(slots: &[Box<dyn Slot>])
Fake slots have special removal and persistence semantics, so no other menu slot may expose their physical backing storage.
Sourcepub(crate) const fn instance(&self) -> MenuInstanceId
pub(crate) const fn instance(&self) -> MenuInstanceId
The identity of the menu being built.
Sourcepub const fn slot_count(&self) -> usize
pub const fn slot_count(&self) -> usize
The number of menu slots added so far.
Sourcepub(crate) fn push_boxed_slot(&mut self, slot: Box<dyn Slot>)
pub(crate) fn push_boxed_slot(&mut self, slot: Box<dyn Slot>)
Appends a single already-erased slot without creating a section.
Sourcepub(crate) fn push_section_slot(
&mut self,
slot: Box<dyn Slot>,
source: &ContainerRef,
source_index: usize,
)
pub(crate) fn push_section_slot( &mut self, slot: Box<dyn Slot>, source: &ContainerRef, source_index: usize, )
Appends a slot whose physical backing must match its declarative source.
Sourcepub(crate) fn claim(&mut self, container: &ContainerRef, range: Range<usize>)
pub(crate) fn claim(&mut self, container: &ContainerRef, range: Range<usize>)
Records that a section covers the container-local range of container.
§Panics
Panics if the range exceeds the container or was already covered by another range.
Sourcepub(crate) fn register_container(&mut self, container: impl Into<ContainerRef>)
pub(crate) fn register_container(&mut self, container: impl Into<ContainerRef>)
Records a container to lock.
Sourcefn owned(&self, section: Section) -> Range<usize>
fn owned(&self, section: Section) -> Range<usize>
Verifies that section was created by this builder.
Sourcefn section_from(&self, start: usize) -> Section
fn section_from(&self, start: usize) -> Section
Returns a section spanning start..self.slots.len().
Source§impl MenuBuilder
impl MenuBuilder
Sourcepub fn grid<R>(
&mut self,
rows: usize,
f: impl FnOnce(&mut GridPlacer<'_>) -> R,
) -> R
pub fn grid<R>( &mut self, rows: usize, f: impl FnOnce(&mut GridPlacer<'_>) -> R, ) -> R
Runs f against a fresh 9-wide, rows-tall grid and appends its slots in row-major order.
Grids compose. Each call covers the next rows rows of the menu. See the
module documentation for placement rules and an example.
§Panics
If rows is zero, if the slots so far do not fill complete rows, or if f leaves cells neither placed nor painted.
Sourcefn flush_grid(&mut self, state: GridState)
fn flush_grid(&mut self, state: GridState)
Emits the resolved grid cells as menu slots in row-major order.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for MenuBuilder
impl !UnwindSafe for MenuBuilder
impl Freeze for MenuBuilder
impl Send for MenuBuilder
impl Sync for MenuBuilder
impl Unpin for MenuBuilder
impl UnsafeUnpin for MenuBuilder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreArc<SyncMutex<>>