Skip to content

Items and Inventory

goshi-hider edited this page Jul 24, 2026 · 1 revision

Items and Inventory

Package: dev.goshi.omnimixin.api.event.item

Item use lifecycle, equipment changes, inventory slot clicks, and block loot drops.

PlayItem

Three events covering the lifecycle of using an item.

// Right-click-to-use items are blocked while sitting on your custom mount.
PlayItem.USE.register(ctx -> {
    if (isRidingCustomMount(ctx.user())) {
        ctx.cancel().cancel();
    }
});

// Custom "use on block" behavior for a wand item.
PlayItem.USE_ON_BLOCK.register(ctx -> {
    if (ctx.stack().isOf(MyItems.TELEPORT_WAND)) {
        teleportPlayerTo(ctx.vanillaContext());
        ctx.cancel().cancel(); // stop vanilla's own use-on-block handling
    }
});

// Custom effect when a bow finishes being drawn and released.
PlayItem.FINISH_USE.register(ctx -> {
    if (ctx.stack().isOf(MyItems.CURSED_BOW) && ctx.user() instanceof PlayerEntity player) {
        applyCurse(player);
    }
});

UseContext(ItemStack stack, World world, PlayerEntity user, Hand hand, Cancellable cancel)USE

UseOnBlockContext(ItemStack stack, ItemUsageContext vanillaContext, Cancellable cancel)USE_ON_BLOCK

FinishUseContext(ItemStack stack, World world, LivingEntity user, Cancellable cancel)FINISH_USE

Note: COOLDOWN from the original spec (item cooldown management) isn't covered yet — see Known Limitations.

PlayEquip.CHANGE

Fires after an entity's equipment slot has already changed — this one is observational rather than preventable, since by the time it fires the swap already happened.

// Grant a buff whenever a player equips a full custom armor set.
PlayEquip.CHANGE.register(ctx -> {
    if (ctx.entity() instanceof PlayerEntity player && isWearingFullSet(player)) {
        applySetBonus(player);
    }
});

EquipContext(LivingEntity entity, EquipmentSlot slot, ItemStack oldStack, ItemStack newStack)

If you need to prevent an equipment change rather than just react to it, you'll want to intervene earlier — for example by cancelling the slot click that triggered it via PlayInventory.SLOT_CLICK below, if the change came from a GUI interaction.

PlayInventory.SLOT_CLICK

Fires when a player clicks a slot in any open screen handler (inventory, chest, crafting table, etc.).

// A "locked" slot that can't be clicked in a custom screen.
PlayInventory.SLOT_CLICK.register(ctx -> {
    if (ctx.handler() instanceof MyCustomScreenHandler custom && custom.isLockedSlot(ctx.slotIndex())) {
        ctx.cancel().cancel();
    }
});

SlotClickContext(ScreenHandler handler, int slotIndex, int button, SlotActionType actionType, PlayerEntity player, Cancellable cancel)

Note: hopper/direct-inventory item transfer (ITEM_TRANSFER/PICKUP_ITEM) isn't covered yet — see Known Limitations.

PlayLoot.MODIFY_DROPS

Fires after a block's loot table has generated its drops, letting you add, remove, or replace items before they actually spawn in the world.

// Guaranteed bonus drop from a specific ore under a lucky-charm buff.
PlayLoot.MODIFY_DROPS.register(ctx -> {
    if (ctx.state().isOf(MyBlocks.RICH_ORE) && wasMinedWithLuckyCharm(ctx.pos())) {
        ctx.drops().add(new ItemStack(MyItems.BONUS_GEM));
    }
});

BlockLootContext(BlockState state, ServerWorld world, BlockPos pos, BlockEntity blockEntity, List<ItemStack> drops)

drops() is a live, mutable list — add to it, remove from it, or clear it entirely to change what actually ends up on the ground.

Note: entity death loot (ENTITY_LOOT) isn't covered yet, since it needs a full loot context (damage source, killer, luck) rather than the simple single call site block drops have — see Known Limitations.

Clone this wiki locally