Class OnDemandGroup

java.lang.Object
com.trevlar.slotkit.api.slot.OnDemandGroup

public final class OnDemandGroup extends Object
A slot group a menu gets on demand: declared once at init, like a ParityGroup, but on no menu until the server adds an instance of it to the menu the player has open, and gone again when the server removes it or the menu closes. For things a player opens and closes while a screen is up (a shulker box opened from a chest's screen, a bundle), as many at once as they like, with nothing on a menu that has none open.
// Common init (both sides): the kind, and the behavior every instance shares.
public static final OnDemandGroup BOX = OnDemandGroup.register("mymod:box",
        SlotSpec.at("slots", MY_CATEGORY).count(27).shiftClickIn(true));
for (int i = 0; i < 27; i++) {
    Window.slot(ModeScope.BOTH, Address.createdSlot(BOX.id(), i)).gate(NO_BOXES_IN_BOXES);
}

// Server, when the player opens a box: its slots join the open menu, the client's too.
OnDemandGroup.Instance open = BOX.add(player, boxStorage);
// ... and when it closes:
open.remove();

Instances

Each instance is a slot group of its own on the menu, with its own id, OnDemandGroup.Instance.id() (mymod:box:slots#0, #1, ...): what CreatedSlot.panelId() reads on its slots, what SlotElement.slot(id, i) and SlotGroupElement show, and what QuickMoveRoutes.Dest.group names. An instance takes the lowest number no live instance of its kind holds on that menu, so numbers are reused and a screen can keep a fixed set of places to show them in.

Behavior is the kind's

Declarations on the kind reach every instance: one on Address.createdSlot(kind.id(), i) applies to slot i of each instance (unless that instance's own address declares otherwise), and the spec's group-level behavior (shiftClickIn, collect, the gate) and its category hold for all of them. A gate that needs to know which instance it judges reads instanceOf(Slot) of GatingContext.slot(); a quick-move route reads it of its source slot. The kind is listed in SlotGroups; its instances are not.

Sync

The server adds and removes; the client follows, told before any of the slots' contents arrive, so both menus hold the same slots at the same indices. The server adds only for a client that runs SlotKit and the kind's mod (add(ServerPlayer, Storage) returns null otherwise). A removed instance's slots stay on the menu, inert (empty to everything, refusing every click), until a new instance of the same kind takes their place, so no other slot's index ever moves while the menu is open. The player's own inventory menu takes no instances: it outlives every screen, and creative's tab copies its slots when the tab opens.

Since 2.1.0.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final class 
    One instance of a kind, on one menu.
  • Method Summary

    Modifier and Type
    Method
    Description
    add(net.minecraft.server.level.ServerPlayer player, Storage storage)
    Adds an instance to the menu player has open, its slots over storage.
    static void
    applyOnClient(com.trevlar.slotkit.network.GroupInstanceS2CPayload p, net.minecraft.world.entity.player.Player player)
    Client: applies what the server sent, to the player's open menu.
    int
    How many slots each instance has.
    id()
    The kind's id: what declarations every instance shares are made on.
    instanceId(int number)
    The id instance number number of this kind has on any menu.
    static @Nullable OnDemandGroup.Instance
    instanceOf(@Nullable net.minecraft.world.inventory.Slot slot)
    The on-demand instance slot belongs to (seeing through creative's wrapper), or null.
    instances(net.minecraft.world.inventory.AbstractContainerMenu menu)
    The live instances of this kind on menu, in the order they were added, on either side.
    static boolean
    isInstance(String slotPanelId)
    Whether slotPanelId is an instance's.
    static @Nullable Address
    The same slot of the kind, for a created slot's address in an instance, or null: where the engine looks when the instance's own address declares nothing.
    static @Nullable SlotGroupId.Created
    kindOf(@Nullable SlotGroupId.Created group)
    The kind a created group is an instance of, or null when it's no instance.
    group's kind when it's an instance, else group.
    register(String owner, SlotSpec spec)
    Registers a kind of on-demand group.
    static void
    replay(net.minecraft.server.level.ServerPlayer player, net.minecraft.world.inventory.AbstractContainerMenu menu)
    Server: tells the client about every instance on menu again, removed ones too, in slot order, so a new client menu for it (one MenuSwitch.back reopened) builds the same slots at the same indices before its contents arrive.
    Every kind's slot count by its slot panel id, for the join handshake.
    The spec it was registered with.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • register

      public static OnDemandGroup register(String owner, SlotSpec spec)
      Registers a kind of on-demand group. Call once at mod init, from the common initializer. The spec gives the slots and their behavior; it declares no storage, since each instance brings its own to add(ServerPlayer, Storage).
      Throws:
      IllegalStateException - after MenuKit's declarations froze, when the spec declares storage, when the owner's mod doesn't declare SlotKit on both sides, or when the same group is registered twice (as either kind of group)
    • id

      public SlotGroupId.Created id()
      The kind's id: what declarations every instance shares are made on.
    • spec

      public SlotSpec spec()
      The spec it was registered with.
    • count

      public int count()
      How many slots each instance has.
    • instanceId

      public SlotGroupId.Created instanceId(int number)
      The id instance number number of this kind has on any menu.
    • add

      public @Nullable OnDemandGroup.Instance add(net.minecraft.server.level.ServerPlayer player, Storage storage)
      Adds an instance to the menu player has open, its slots over storage. Server only, on the server thread, and not from inside a click. The client hears at once; the slots' contents follow with the menu's next sync.
      Returns:
      the instance, or null when the player's client can't follow (no SlotKit, or not this kind's mod)
      Throws:
      IllegalStateException - when the player has only their own inventory open
      IllegalArgumentException - when storage isn't count() slots
    • instances

      public List<OnDemandGroup.Instance> instances(net.minecraft.world.inventory.AbstractContainerMenu menu)
      The live instances of this kind on menu, in the order they were added, on either side.
    • instanceOf

      public static @Nullable OnDemandGroup.Instance instanceOf(@Nullable net.minecraft.world.inventory.Slot slot)
      The on-demand instance slot belongs to (seeing through creative's wrapper), or null.
    • applyOnClient

      @Internal public static void applyOnClient(com.trevlar.slotkit.network.GroupInstanceS2CPayload p, net.minecraft.world.entity.player.Player player)
      Client: applies what the server sent, to the player's open menu.
    • replay

      @Internal public static void replay(net.minecraft.server.level.ServerPlayer player, net.minecraft.world.inventory.AbstractContainerMenu menu)
      Server: tells the client about every instance on menu again, removed ones too, in slot order, so a new client menu for it (one MenuSwitch.back reopened) builds the same slots at the same indices before its contents arrive.
    • kindOf

      @Internal public static @Nullable SlotGroupId.Created kindOf(@Nullable SlotGroupId.Created group)
      The kind a created group is an instance of, or null when it's no instance.
    • kindOrSelf

      @Internal public static SlotGroupId kindOrSelf(SlotGroupId group)
      group's kind when it's an instance, else group.
    • isInstance

      @Internal public static boolean isInstance(String slotPanelId)
      Whether slotPanelId is an instance's.
    • kindAddress

      @Internal public static @Nullable Address kindAddress(Address address)
      The same slot of the kind, for a created slot's address in an instance, or null: where the engine looks when the instance's own address declares nothing.
    • slotCounts

      @Internal public static Map<String,Integer> slotCounts()
      Every kind's slot count by its slot panel id, for the join handshake.