Skip to content

ComposeItemContainerMenu

abstract class ComposeItemContainerMenu<SELF : ComposeItemContainerMenu<SELF>>(
    type: MenuType<SELF>, 
    id: Int, 
    playerInventory: Inventory, 
    itemAccess: ItemContainerAccess
) : ComposeContainerMenuBase<SELF> , SyncedItemHolder

Base class for net.minecraft.world.item.ItemStack-backed Compose container menus - e.g. a backpack/bag with its own GUI. The ComposeBlockContainerMenu equivalent for items.

See ComposeContainerMenuBase for slot pre-registration/positioning behavior, shared with net.kernelpanicsoft.archie.gui.ComposeBlockContainerMenu - this class only adds the item-specific pieces: locating the backing stack via itemAccess, the itemState sync path, and periodic validity checking via ItemStateManager.

Subclassing

class MyBackpackMenu(id: Int, inventory: Inventory, access: ItemContainerAccess) :
    ComposeItemContainerMenu<MyBackpackMenu>(MY_MENU_TYPE, id, inventory, access) {

    @Sync
    var progress by holder.intField()

    override fun registerSlotHandlers() {
        handler("inventory", holder.itemField(27))
    }
}

Parameters

  • SELF: The concrete menu subclass (self-referential for the MenuType).

  • type: The registered MenuType for this menu.

  • id: The container id assigned by the server.

  • playerInventory: The opening player's inventory.

  • itemAccess: Locates the backing net.minecraft.world.item.ItemStack and reports whether this menu should stay open.

Constructors

ComposeItemContainerMenu

constructor(
    type: MenuType<SELF>, 
    id: Int, 
    playerInventory: Inventory, 
    itemAccess: ItemContainerAccess
)

Parameters

  • SELF: The concrete menu subclass (self-referential for the MenuType).

  • type: The registered MenuType for this menu.

  • id: The container id assigned by the server.

  • playerInventory: The opening player's inventory.

  • itemAccess: Locates the backing net.minecraft.world.item.ItemStack and reports whether this menu should stay open.

Properties

carried

open var carried: ItemStack?

containerId

items

open val items: NonNullList<ItemStack?>?

itemState

Client- and server-side sync state for this menu's own @Sync-annotated holder fields.

lastSlots

val lastSlots: NonNullList<ItemStack?>?

ready

var ready: Boolean

true once repositionSlots has run at least once and slot pixel positions are valid.

remoteSlots

val remoteSlots: NonNullList<ItemStack?>?

screenLeftPos

The screen's leftPos offset — set by ComposeContainerScreen so that absolute Compose coordinates can be converted to slot-relative coordinates that vanilla's item rendering expects (vanilla renders items at leftPos + slot.x).

screenTopPos

The screen's topPos offset — set by ComposeContainerScreen so that absolute Compose coordinates can be converted to slot-relative coordinates that vanilla's item rendering expects (vanilla renders items at topPos + slot.y).

slotData

The most recently reported SlotData from the Compose layout. On the server this is the authoritative source of slot group sizes. On the client it is received from the server via a net.kernelpanicsoft.archie.networking.NetworkChannel.

slots

val slots: NonNullList<Slot?>?

stateId

open val stateId: Int

type

open val type: MenuType<*>?

Functions

addSlotListener

open fun addSlotListener(listener: ContainerListener?)

broadcastChanges

open fun broadcastChanges()

broadcastFullState

open fun broadcastFullState()

canDragTo

open fun canDragTo(slot: Slot?): Boolean

canTakeItemForPickAll

open fun canTakeItemForPickAll(stack: ItemStack?, slot: Slot?): Boolean

clicked

open override fun clicked(
    slotId: Int, 
    button: Int, 
    clickType: ClickType, 
    player: Player
)

clickMenuButton

open fun clickMenuButton(player: Player?, id: Int): Boolean

findSlot

open fun findSlot(container: Container?, slotIndex: Int): OptionalInt?

getSlot

open fun getSlot(slotId: Int): Slot?

incrementStateId

open fun incrementStateId(): Int

initializeContents

open fun initializeContents(
    stateId: Int, 
    items: List<ItemStack?>?, 
    carried: ItemStack?
)

isSlotVisible

fun isSlotVisible(slotIndex: Int): Boolean

Whether the slot at slotIndex currently overlaps its group's clip bounds (if it has any, i.e. it sits inside a net.kernelpanicsoft.archie.gui.composables.containers.Scrollable).

isValidSlotIndex

open fun isValidSlotIndex(slotIndex: Int): Boolean

onSyncedPropertyChanged

open override fun <T> onSyncedPropertyChanged(
    name: String, 
    serializer: KSerializer<T>, 
    value: T
)

Called on every write to a @Sync-annotated NBTHolder.item-delegated property named name.

quickMoveStack

open override fun quickMoveStack(player: Player, index: Int): ItemStack

Shift-click handling: menu slots move into the player inventory/hotbar, and player slots move into the menu, falling back between main inventory and hotbar when the menu has no room. Slot ranges are derived from slots.size rather than hardcoded, since the number of menu slots varies with which groups are enabled.

refreshSlotPositions

Re-derives every Slot's pixel position from the current slotData without touching slot identity or slotHandlers. Call after screenLeftPos/screenTopPos change - slot coordinates have the screen offset baked into their subtraction (see repositionSlots), so they go stale whenever the screen recenters, independent of whether Compose's own slot layout changed.

registerSyncedProperty

open override fun <T> registerSyncedProperty(name: String, serializer: KSerializer<T>)

Called once, at property-declaration time, for every @Sync-annotated NBTHolder.item- delegated property named name - independent of whether its value has ever actually been written. Needed so a serializer is available to decode an incoming edit even for a property whose value came from an existing stack's already-populated data (where the delegate's own initial-value write, which onSyncedPropertyChanged would otherwise piggyback on, never runs) - mirrors why net.kernelpanicsoft.archie.gui.blockentity.BlockEntityStateContainer has its own separate setPropertySerializer call distinct from updateProperty. No-op by default for implementations that don't need it.

removed

open override fun removed(player: Player)

removeSlotListener

open fun removeSlotListener(listener: ContainerListener?)

resumeRemoteUpdates

open fun resumeRemoteUpdates()

sendAllDataToRemote

open fun sendAllDataToRemote()

setData

open fun setData(id: Int, data: Int)

setItem

open fun setItem(
    slotId: Int, 
    stateId: Int, 
    stack: ItemStack?
)

setRemoteCarried

open fun setRemoteCarried(remoteCarried: ItemStack?)

setRemoteSlot

open fun setRemoteSlot(slot: Int, stack: ItemStack?)

setRemoteSlotNoCopy

open fun setRemoteSlotNoCopy(slot: Int, stack: ItemStack?)

setSynchronizer

open fun setSynchronizer(synchronizer: ContainerSynchronizer?)

slotClipBounds

fun slotClipBounds(slotIndex: Int): IntRect?

slotLayerDepth

fun slotLayerDepth(slotIndex: Int): Int

slotsChanged

open fun slotsChanged(container: Container?)

stillValid

open override fun stillValid(player: Player): Boolean

suppressRemoteUpdates

transferState

open fun transferState(menu: AbstractContainerMenu?)

updateSlotData

Called by the Slot composable once its absolute screen position is known.