Class SlotOperations
What an operation is
A slot has two independent facts about it, and keeping them apart is the whole design:- Category, what the slot is
(
SlotGroupCategory). Identity. A pocket declaredPLAYER_INVENTORYis inventory storage, and every mod that searches the inventory should find it. - Operations, what may be done to it. Shift-click, double-click collect, drag-fill, a pickup landing in it, and whatever an inventory mod adds next.
The vocabulary is open
An operation is named by aBehaviorKey, so any mod can add one: it
declares its own key, defines it here so other mods
can discover it, ships a name and a description for it (below), asks
allows(SlotRef, BehaviorKey) in its own code before acting, and sends any clicks it performs
under as(BehaviorKey, Runnable). SlotKit needs no change for a new
operation to exist. Vanilla's own operations are BehaviorKeys.VANILLA_OPERATIONS,
split one key per thing a player can do to a slot, and enforced at vanilla's seams
by SlotKit itself.
Name and description
A settings screen that lists operations needs words for them.name(BehaviorKey) and
description(BehaviorKey) are translatable components on keys derived from the id,
the way keybinds work; a mod ships the lines in its own lang file:
"slot_operation.mymod.restock_take": "Restock takes from", "slot_operation.mymod.restock_take.description": "Auto-restock may pull a refill out of this slot."A missing line shows the key itself, Minecraft's own fallback.
Role
define(BehaviorKey, Role) records whether an operation takes items out
of a slot, puts items in, or both (role(BehaviorKey)). A lock that protects an item
already in a slot only cares about what takes it out, so a settings screen can
hide the rest for any mod's operations, not just vanilla's. An operation that
moves items between two slots is two keys, one TAKE and one PUT.
Where an operation applies
define(BehaviorKey, Role, AppliesTo) also records which slot groups the
operation can act on at all, so a settings screen never offers a box the
operation could never touch (appliesTo(BehaviorKey, SlotGroupId),
groups(BehaviorKey)). An operation names the vanilla groups it
applies to; every group a mod adds applies automatically, unless the operation
opts out of it by id or by SlotGroupSet. An operation defined without
saying applies to every group, so nothing defined before this existed changes.
SlotKit declares vanilla's own operations from what vanilla does: nothing puts
into an output slot, the crafter's result can't be touched at all, double-click
collect skips the results vanilla's menus exclude, and a world pickup lands only
in the hotbar, the main inventory and the offhand.
This is a declaration, not a rule SlotKit enforces: vanilla's seams already act only where vanilla does, and a mod's own operation acts where its code does. It is what a consumer reads to know where an operation can reach.
With no screen open
Q, Ctrl-Q and F while playing are the sameDROP, DROP_STACK and
OFFHAND_SWAP operations, on the selected hotbar slot; an offhand swap
also needs the offhand slot to allow it. To the player Q is Q, screen or not.
Who says what a slot allows
Two mechanisms, one subtractive:- The cascade is what the slot's author declared, most specific wins:
per-slot declaration > the slot's group > the group's category > the key's default
This is the window's ordinary cascade; the group and the category are two rungs inside its per-group level, ordered byGroupKey.precedence().inherent(ModeScope, SlotGroupCategory, BehaviorKey, V)declares the category rung. A vanilla slot's group and category are one rung: vanilla contributes one group per category on a menu. Every built-in operation defaults toTRUE, so a slot nobody declared on is exactly vanilla. - A veto is a rule some other mod lays on top, and it can only say
no. A player's lock is the case: the player's policy over whatever the
slot's author allowed. Written as a per-slot declaration it would overwrite
the author's own settings and have nothing to restore on unlock; as a
SlotOperations.Vetoit sits beside the cascade and only subtracts.
allows(SlotRef, BehaviorKey) is the one question: the cascade says yes and no veto says no.
A veto that decides by slot group registers as a SlotOperations.GroupVeto: it is handed
the slot's group, resolved once per question (SlotGroups.of(SlotRef)), rather than
working it out again on every slot of every click.
A veto that needs to see the item coming in registers as a SlotOperations.PutVeto.
It is asked only by allowsPut(SlotRef, BehaviorKey, ItemStack), which every put seam uses with the
stack it is about to place: "only into a container that already holds this
item" is a put veto.
Simulated clicks
A mod that performs its operation by sending vanilla clicks wraps them:SlotOperations.as(RESTOCK_TAKE, RESTOCK_PUT, () -> sendClicks());Each click sent inside the block carries the operation it serves: the first for the slot it takes from, the second for the slot it puts into. The vetoes judge the carried operation, so a lock that refuses shift-click but allows restock lets the restock's shift-click through. The slot's author still judges the gesture: a group that sits out shift-click refuses a restock that arrives as a shift-click. A mod that wants to know first asks
allows about both. The tag reaches
the integrated server too. Clicks must be sent inside the block, on the calling
thread; a click scheduled for later is not tagged. A simulated click that is not
wrapped counts as the gesture it looks like, a manual click included.
Init-time reads are the one exception to "declare anywhere". Every
built-in operation is SERVER tier, and SlotKit installs the server
tier from its own initializer. Fabric does not order entrypoints between mods,
so a consumer whose init runs first will see resolve answer the key's
library default, and a declaration it makes there is buffered until the tier
installs. Declare at init and read during play, as consumers normally do.
Thread-safe; every method is safe to call from mod init on any thread.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordWhich slot groups an operation can act on.static interfaceASlotOperations.Vetothat is handed the slot's group:SlotGroups.of(SlotRef)of the slot, resolved once per question and shared by every group veto, ornullwhen the slot is in no known group.static interfaceA veto on putting a particular item into a slot, handed the stack about to land (incoming, never empty; read it, don't change it) along with the slot's group as aSlotOperations.GroupVetogets it.static enumWhat an operation does to the slot it acts on.static interfaceA rule that refuses an operation on a slot, laid over the cascade by a mod that is not the slot's author. -
Method Summary
Modifier and TypeMethodDescriptionstatic Collection<BehaviorKey<?>> all()Every defined operation, in definition order.static booleanallows(SlotRef ref, BehaviorKey<TriBool> operation) Whetheroperationmay act on the slotrefdescribes: the cascade resolvesTRUEand noSlotOperations.Vetodenies it.static booleanallows(net.minecraft.world.Container container, int containerSlot, @Nullable net.minecraft.world.entity.player.Player player, BehaviorKey<TriBool> operation) allows(SlotRef, BehaviorKey)for a slot reached with no menu open.static booleanallows(net.minecraft.world.inventory.AbstractContainerMenu menu, net.minecraft.world.inventory.Slot slot, @Nullable net.minecraft.world.entity.player.Player player, BehaviorKey<TriBool> operation) allows(SlotRef, BehaviorKey)for a slot on an open menu.static booleanallowsGesture(SlotRef ref, BehaviorKey<TriBool> gesture) What a vanilla seam asks for the gesture it is running:allows(SlotRef, BehaviorKey), or, when the click on this thread carries an operation (as(BehaviorKey, Runnable)), the slot's cascade on the gesture andallowson the carried operation for the gesture's role.static booleanallowsGesture(net.minecraft.world.inventory.AbstractContainerMenu menu, net.minecraft.world.inventory.Slot slot, @Nullable net.minecraft.world.entity.player.Player player, BehaviorKey<TriBool> gesture) allowsGesture(SlotRef, BehaviorKey)for a slot on an open menu.static booleanallowsPut(SlotRef ref, BehaviorKey<TriBool> operation, net.minecraft.world.item.ItemStack incoming) allows(SlotRef, BehaviorKey), then everySlotOperations.PutVetowith the stack about to land.static booleanallowsPutGesture(SlotRef ref, BehaviorKey<TriBool> gesture, net.minecraft.world.item.ItemStack incoming) allowsGesture(SlotRef, BehaviorKey)for a put seam that knows the stack about to land: the put vetoes judge it along with the operation the gesture serves.static SlotOperations.AppliesToappliesTo(BehaviorKey<?> operation) The slot groupsoperationwas defined to apply to;SlotOperations.AppliesTo.EVERY_GROUPfor one defined without saying, or never defined.static booleanappliesTo(BehaviorKey<?> operation, SlotGroupId group) Whetheroperationcan act on slots ingroup.static voidas(BehaviorKey<TriBool> take, BehaviorKey<TriBool> put, Runnable clicks) Sendsclicksas the operation pair:takefor the slots they take from,putfor the slots they put into.static voidas(BehaviorKey<TriBool> operation, Runnable clicks) Sendsclicksasoperation, for both the slots they take from and put into.static @Nullable BehaviorKey<?> byId(net.minecraft.resources.Identifier id) The defined operation with this id, ornull.static voiddefine(BehaviorKey<?> operation) define(BehaviorKey, Role)for an operation that does not say what it does to a slot, which is read asSlotOperations.Role.BOTH.static voiddefine(BehaviorKey<?> operation, SlotOperations.Role role) Publishesoperationso other mods can discover it throughall(), with theSlotOperations.Roleit plays on a slot.static voiddefine(BehaviorKey<?> operation, SlotOperations.Role role, SlotOperations.AppliesTo appliesTo) define(BehaviorKey, Role)with the slot groups the operation can act on; see "Where an operation applies" in the class doc.static net.minecraft.network.chat.Componentdescription(BehaviorKey<?> operation) One or two sentences on what the operation does to a slot, for a settings list.static List<SlotGroupId> groups(BehaviorKey<?> operation) Every declared slot group (SlotGroups.all()) thatoperationapplies to, in that order: the list a settings screen offers for it.static <V> voidinherent(com.trevlar.menukit.api.panel.ModeScope scope, SlotGroupCategory category, BehaviorKey<V> operation, V value) Declaresvalueas the default foroperationon every slot incategorythat does not declare its own (the category rung), while the acting player's mode is inscope.static <V> voidinherent(SlotGroupCategory category, BehaviorKey<V> operation, V value) Deprecated, for removal: This API element is subject to removal in a future version.static StringlangKey(BehaviorKey<?> operation) The translation key an operation's name lives under:slot_operation.<namespace>.<path>.static net.minecraft.network.chat.Componentname(BehaviorKey<?> operation) The operation's display name, for a settings list.static @Nullable SlotOperations.Rolerole(BehaviorKey<?> operation) The roleoperationwas defined with, ornullif it was never defined.static voidveto(com.trevlar.menukit.api.panel.ModeScope scope, SlotOperations.GroupVeto veto) veto(ModeScope, Veto)for a veto that is handed the slot's group.static voidveto(com.trevlar.menukit.api.panel.ModeScope scope, SlotOperations.Veto veto) Registers a veto that applies while the acting player's mode is inscope.static voidveto(SlotOperations.GroupVeto veto) Deprecated, for removal: This API element is subject to removal in a future version.since 2.1.0, name the mode:veto(ModeScope.BOTH, veto).static voidveto(SlotOperations.Veto veto) Deprecated, for removal: This API element is subject to removal in a future version.since 2.1.0, name the mode:veto(ModeScope.BOTH, veto).static voidvetoPut(com.trevlar.menukit.api.panel.ModeScope scope, SlotOperations.PutVeto veto) Registers aSlotOperations.PutVetothat applies while the acting player's mode is inscope, read per question asveto(ModeScope, Veto)is.static voidvetoPut(ModeScope, PutVeto)in both modes.
-
Method Details
-
define
Publishesoperationso other mods can discover it throughall(), with theSlotOperations.Roleit plays on a slot. Idempotent per id; a second definition of the same id with a different key or a different role is refused rather than silently replacing the first, because mods resolve against whichever key they were compiled with.Defining is not required to use a key, the window resolves any
BehaviorKey, it is how an operation becomes part of the shared vocabulary instead of a private one. -
define
public static void define(BehaviorKey<?> operation, SlotOperations.Role role, SlotOperations.AppliesTo appliesTo) define(BehaviorKey, Role)with the slot groups the operation can act on; see "Where an operation applies" in the class doc. A second definition with a differentappliesTois refused, as a different role is. -
define
define(BehaviorKey, Role)for an operation that does not say what it does to a slot, which is read asSlotOperations.Role.BOTH. A no-op for an operation already defined, whatever its role. -
all
Every defined operation, in definition order. -
byId
The defined operation with this id, ornull. -
role
The roleoperationwas defined with, ornullif it was never defined. -
appliesTo
The slot groupsoperationwas defined to apply to;SlotOperations.AppliesTo.EVERY_GROUPfor one defined without saying, or never defined. -
appliesTo
Whetheroperationcan act on slots ingroup. -
groups
Every declared slot group (SlotGroups.all()) thatoperationapplies to, in that order: the list a settings screen offers for it. To filterSlotGroups.listing()instead, keep an entry when any of its groups applies. -
langKey
The translation key an operation's name lives under:slot_operation.<namespace>.<path>. -
name
The operation's display name, for a settings list. -
description
One or two sentences on what the operation does to a slot, for a settings list. -
inherent
@Deprecated(since="2.1.0", forRemoval=true) public static <V> void inherent(SlotGroupCategory category, BehaviorKey<V> operation, V value) Deprecated, for removal: This API element is subject to removal in a future version.since 2.1.0, name the mode:inherent(ModeScope.BOTH, category, operation, value).inherent(ModeScope, SlotGroupCategory, BehaviorKey, Object)in both modes. -
veto
Deprecated, for removal: This API element is subject to removal in a future version.since 2.1.0, name the mode:veto(ModeScope.BOTH, veto).veto(ModeScope, Veto)in both modes. -
veto
Deprecated, for removal: This API element is subject to removal in a future version.since 2.1.0, name the mode:veto(ModeScope.BOTH, veto).veto(ModeScope, GroupVeto)in both modes. -
vetoPut
vetoPut(ModeScope, PutVeto)in both modes. Since 2.3.0. -
as
Sendsclicksasoperation, for both the slots they take from and put into. -
as
Sendsclicksas the operation pair:takefor the slots they take from,putfor the slots they put into. See the class doc. -
allows
Whetheroperationmay act on the slotrefdescribes: the cascade resolvesTRUEand noSlotOperations.Vetodenies it. Every operation, vanilla's and a mod's own, asks this before touching a slot. -
allowsPut
public static boolean allowsPut(SlotRef ref, BehaviorKey<TriBool> operation, net.minecraft.world.item.ItemStack incoming) allows(SlotRef, BehaviorKey), then everySlotOperations.PutVetowith the stack about to land. What a put asks when it knows the item; an emptyincomingputs nothing, so no put veto is asked. Since 2.3.0. -
allows
public static boolean allows(net.minecraft.world.inventory.AbstractContainerMenu menu, net.minecraft.world.inventory.Slot slot, @Nullable net.minecraft.world.entity.player.Player player, BehaviorKey<TriBool> operation) allows(SlotRef, BehaviorKey)for a slot on an open menu. -
allows
public static boolean allows(net.minecraft.world.Container container, int containerSlot, @Nullable net.minecraft.world.entity.player.Player player, BehaviorKey<TriBool> operation) allows(SlotRef, BehaviorKey)for a slot reached with no menu open. -
allowsGesture
What a vanilla seam asks for the gesture it is running:allows(SlotRef, BehaviorKey), or, when the click on this thread carries an operation (as(BehaviorKey, Runnable)), the slot's cascade on the gesture andallowson the carried operation for the gesture's role. Library seams only; a mod asksallows(SlotRef, BehaviorKey)about its own operation. -
allowsPutGesture
@Internal public static boolean allowsPutGesture(SlotRef ref, BehaviorKey<TriBool> gesture, net.minecraft.world.item.ItemStack incoming) allowsGesture(SlotRef, BehaviorKey)for a put seam that knows the stack about to land: the put vetoes judge it along with the operation the gesture serves. Library seams only; a mod asksallowsPut(SlotRef, BehaviorKey, ItemStack). Since 2.3.0. -
allowsGesture
@Internal public static boolean allowsGesture(net.minecraft.world.inventory.AbstractContainerMenu menu, net.minecraft.world.inventory.Slot slot, @Nullable net.minecraft.world.entity.player.Player player, BehaviorKey<TriBool> gesture) allowsGesture(SlotRef, BehaviorKey)for a slot on an open menu.
-
inherent(ModeScope.BOTH, category, operation, value).