Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Using an item

Verified against Minecraft 26.2 · Part VII · A player holds the use key on a piece of cooked beef, then holds it on a bow — one countdown, two endings.

You hold the use button on cooked beef and thirty-two ticks later you have eaten it. You hold the same button on a bow and nothing happens at all until you let go. These are the same machine: Item.use starts both, LivingEntity.useItemRemaining counts down on the client and the server for both, ItemStack.onUseTick runs every tick on both sides, and LivingEntity.stopUsingItem ends both. What differs is whether the count is allowed to mean anything — and the consequence is stranger than the difference. The client’s countdown does not stop at zero. The meal ends because one byte arrives from the server, a ClientboundEntityEventPacket carrying EntityEvent.USE_ITEM_COMPLETE. The bow’s countdown starts at 72000 and would take an hour to expire, so the shot is fired by a ServerboundPlayerActionPacket instead — the same packet, carrying the same action, that the meal would read as the player changed their mind.

The cast

classwhat it decidesthread
Minecraftwhich key edge starts a use, and which one ends itclient main
MultiPlayerGameModethe client’s own copy of the use, and the packet that reports itclient main
ServerGamePacketListenerImplwhich handler each packet reaches, and whether the rotation is snapped firstserver main
LivingEntitythe countdown, the synched flags, and both endingsboth main
ItemStackthe dispatch into the item, and the after-use side effectsboth
ItemItem.use, Item.getUseDuration, Item.releaseUsing, Item.useOnReleaseboth
Consumableeverything the meal does, on both sidesboth
ProjectileWeaponItemammo, spread and the arrow — the counting on both sides, the spawning only on the serverboth, but only the server’s counts

The block-target branch of a use — right-clicking a chest rather than the air — leaves at MultiPlayerGameMode.useItemOn and belongs to block interaction; the stack itself is items and stacks.

The two paths, side by side

the mealthe bow
what Item.use doesthe default body finds DataComponents.CONSUMABLE and calls Consumable.startConsumingBowItem.use overrides it, checks Player.getProjectile, calls LivingEntity.startUsingItem
the refusalConsumable.canConsume asks Player.canEat, for food onlyno arrow anywhere and no infinite materials — InteractionResult.FAIL
Item.getUseDurationConsumable.consumeTicks, 32 for Consumables.DEFAULT_FOOD72000, Item.APPROXIMATELY_INFINITE_USE_DURATION in all but name
what ItemStack.onUseTick doesparticles and the chew sound, on both sidesnothing — BowItem does not override Item.onUseTick
how it endsthe count reaches zero on the serverthe use key comes up on the client
the packet that ends itClientboundEntityEventPacket, downwardServerboundPlayerActionPacket, upward
is the ending acknowledgedyes — that is the acknowledgementno, nothing answers a release
Item.releaseUsingnot overridden, returns false, so letting go simply abandons the mealBowItem.releaseUsing is where the whole shot lives
ItemStack.useOnReleasefalsealso false
what the client predictsthe entire meal, twice overthe animation, and nothing else

The last-but-one row is the one that looks wrong. ItemStack.useOnRelease is the third term of the completion guard and it is the obvious name for “this item is finished by letting go” — but CrossbowItem.useOnRelease is its only override in the tree. The bow and the trident return Item.useOnRelease’s default false. They are release-ended not because a predicate says so, but because their Item.getUseDuration is an hour long and their Item.releaseUsing does the work. The spyglass returns the default too and is not release-ended at all: at 1200 ticks its countdown really can run out.

Starting: the client finishes before it speaks

Minecraft.handleKeybinds sees the press and calls Minecraft.startUseItem, which sets the four-tick Minecraft.rightClickDelay itself, refuses while LocalPlayer.isHandsBusy, and walks both hands for a target. With nothing under the crosshair it reaches MultiPlayerGameMode.useItem, which opens a prediction window first (MultiPlayerGameMode.startPrediction, prediction and acks) and does everything else inside it: it builds the ServerboundUseItemPacket — hand, sequence number and both rotations — then consults the client’s own ItemCooldowns, and runs ItemStack.use locally first only if the item is off cooldown. The packet goes up either way; the cooldown suppresses the prediction, not the report of it. The prediction is complete before a byte leaves the client, for the meal and the bow alike. Both answer InteractionResult.CONSUME, whose InteractionResult.SwingSource.NONE is why neither swings the arm, although ItemInHandRenderer.itemUsed still runs — the small dip the item makes as the use begins. An instant use, one whose ItemStack.getUseDuration is zero, returns its outcome the other way instead, through InteractionResult.Success.heldItemTransformedTo, which both game modes unwrap and write back into the hand.

On the server, ServerGamePacketListenerImpl.handleUseItem acknowledges the sequence number, snaps the player’s rotation to the one in the packet, and calls ServerPlayerGameMode.useItem. That snap is what makes the release strange later, because the release packet does no such thing. And ServerPlayerGameMode.useItem ends on a deliberate omission: it normally re-sends the player’s inventory with AbstractContainerMenu.sendAllDataToRemote (containers and menus), but not when the use it just ran started a multi-tick one. While you are eating or drawing, the server declines to correct your inventory.

While it runs: the flag on the wire and the flag the client believes

LivingEntity.startUsingItem writes two bits of LivingEntity.DATA_LIVING_ENTITY_FLAGS (synched entity data) — bit one for using, bit two assigned the hand, so a main-hand use clears it — and only on the server. LivingEntity.isUsingItem and LivingEntity.getUsedItemHand read those bits, which is how every other client knows your arm is up.

Your own client does not read them. LocalPlayer.isUsingItem overrides the base and returns a private local flag set by LocalPlayer.startUsingItem; LocalPlayer.getUsedItemHand likewise answers from a local field. Reconciliation happens afterwards, in both directions: LocalPlayer.onSyncedDataUpdated compares the arriving bits with the local flag and will start a use the client never predicted, or stop one it did. The base LivingEntity.onSyncedDataUpdated makes the matching repair on every other entity’s copy — it adopts the held stack and re-derives LivingEntity.useItemRemaining from ItemStack.getUseDuration, which is why a remote player drawing a bow animates correctly although your client never saw the press.

One abandonment rule is shared, and it lives a level above the countdown. LivingEntity.tick calls the private LivingEntity.updatingUsingItem, which compares the hand’s current stack with the remembered one using ItemStack.isSameItem and calls LivingEntity.stopUsingItem if they differ; only on a match does it call LivingEntity.updateUsingItem, the countdown proper. The comparison is item identity, not components, so swapping a bowl for a stew aborts the meal while a durability tick on the bow does not abort the draw.

Every tick, and what the bow does instead

LivingEntity.updateUsingItem offers ItemStack.onUseTick the count before it decrements, so a thirty-two-tick meal is offered 32 down to 1 and never 0. For the meal that one call is the whole visible experience: Consumable.shouldEmitParticlesAndSounds is true once more than Consumable.CONSUME_EFFECTS_START_FRACTION of the duration has elapsed and the remaining count is a multiple of Consumable.CONSUME_EFFECTS_INTERVAL, and Consumable.emitParticlesAndSounds then spawns five item particles through LivingEntity.spawnItemParticles — behind Consumable.hasConsumeParticles, which drinks turn off — and plays the chew sound, which they do not. Level.addParticle does nothing on the server, so the crumbs are pure client simulation.

For the bow the call does nothing whatever: BowItem does not override Item.onUseTick, and the base body is empty. Everything you see while drawing is the renderer reading the same counter the logic is decrementing. ItemInHandRenderer computes the draw curve for ItemUseAnimation.BOW from LivingEntity.getUseItemRemainingTicks, and the three-stage bow texture is not code at all: items/bow.json is a condition on using_item wrapping a range_dispatch on the use_duration property (UseDuration), scaled so its thresholds are fractions of BowItem.MAX_DRAW_DURATION.

The crossbow is the exception that makes the rule legible. It does override Item.onUseTick, and that body is entirely server-side: it plays the three CrossbowItem.ChargingSounds at fixed fractions of CrossbowItem.getChargeDuration and, on reaching one, writes DataComponents.CHARGED_PROJECTILES onto the stack. Its client half is a render-thread computation — CrossbowPull and ItemInHandRenderer both call CrossbowItem.getChargeDuration, which calls EnchantmentHelper.modifyCrossbowChargingTime (enchantments). An enchantment hook, evaluated on the render thread, once per frame, to pick one of three textures.

For a 1.21-era reader. There is no bow-pull item property class left to hunt for. The old pulling / pull pair is now the shared UseDuration range-select property plus a using_item condition, both declared in the item’s JSON; the crossbow keeps a bespoke one, CrossbowPull, only because its denominator is enchantable.

Moving while you use

Neither path slows you through movement code — both read one component. LocalPlayer.modifyInput scales the movement input by LocalPlayer.itemUseSpeedMultiplier, which reads UseEffects.speedMultiplier off the stack, unless the player is riding, and LocalPlayer.isSlowDueToUsingItem blocks sprinting because UseEffects.canSprint is false. The famous twenty per cent is the default in UseEffects.DEFAULT, which sits in DataComponents.COMMON_ITEM_COMPONENTS, so every item has one — and neither cooked beef nor the bow overrides it, which is why drawing a bow slows you by exactly as much as eating does, through exactly the same field. Item.Properties.spear is the definition that overrides it outright, with a UseEffects that permits sprinting, suppresses vibrations and multiplies speed by one; the attack that ends that use is a different packet again (the sword swing).

The ending, in one picture

flowchart TD
    T["LivingEntity.updateUsingItem, both sides, every tick"]
    T --> A["ItemStack.onUseTick with the count before the decrement"]
    A --> B["decrement LivingEntity.useItemRemaining"]
    B --> C{"reached zero"}
    C -- no --> T
    C -- yes --> D{"on the server"}
    D -- "no, this is the client" --> W["keep counting into the negatives and wait"]
    D -- yes --> E{"ItemStack.useOnRelease"}
    E -- "false, everything but a crossbow" --> F["LivingEntity.completeUsingItem"]
    E -- "true, a crossbow" --> T
    F --> G["ServerPlayer.completeUsingItem sends ClientboundEntityEventPacket 9 first"]
    G --> H["ItemStack.finishUsingItem, then LivingEntity.stopUsingItem"]
    R["the use key comes up, Minecraft.handleKeybinds"] --> S["MultiPlayerGameMode.releaseUsingItem sends RELEASE_USE_ITEM, then releases locally"]
    S --> P["ServerGamePacketListenerImpl.handlePlayerAction, no ack, no sequence"]
    P --> Q["LivingEntity.releaseUsingItem, each side on its own copy"]
    Q --> K["ItemStack.releaseUsing, then LivingEntity.stopUsingItem either way"]
    K -- "Item.releaseUsing returned true" --> L["the shot, then the after-use side effects"]
    K -- "returned false" --> M["the meal is simply abandoned"]

The client’s branch has no exit. Nothing on the client ever reaches LivingEntity.completeUsingItem from the countdown — it is called from Player.handleEntityEvent when event 9 arrives, and nowhere else on that side. The counter meanwhile keeps falling past zero and only the renderer notices: ItemInHandRenderer draws a use pose solely while LivingEntity.getUseItemRemainingTicks is positive, so the arm drops at tick 32 whether or not the packet has landed.

And ItemStack.useOnRelease does not mean “ends on release”. It means do not let the countdown finish this, and give it one more tick when the key comes up: LivingEntity.releaseUsingItem calls LivingEntity.updatingUsingItem again when it is true, so a crossbow gets a final CrossbowItem.onUseTick in which it can still latch the charge. No other item asks for that. Release is also not only a key-up — LivingEntity.releaseUsingItem has five other call sites: LivingEntity.completeUsingItem itself, when the stack turned out not to match the hand; CrossbowAttack and RangedCrossbowAttackGoal, which is how a pillager fires (AI goals and brains); and BrushItem.onUseTick twice, ending its own use from inside the tick.

The meal, tick by tick

sequenceDiagram
    participant MC as Minecraft
    participant LP as LocalPlayer
    participant MPGM as MultiPlayerGameMode
    participant Wire as the network
    participant SGPL as ServerGamePacketListenerImpl
    participant SP as ServerPlayer
    participant Cons as Consumable

    Note over MC,Cons: tick 0, the press
    MC->>MPGM: startUseItem, nothing under the crosshair
    MPGM->>Cons: ItemStack.use, the default Item.use finds DataComponents.CONSUMABLE
    Cons->>LP: startConsuming, canConsume asks Player.canEat, then startUsingItem
    MPGM->>Wire: ServerboundUseItemPacket, hand and sequence and both rotations
    Wire->>SGPL: handleUseItem acks the sequence and snaps the rotation
    SGPL->>SP: the same Item.use, remaining = 32, the two flag bits are written
    Note over MC,Cons: ticks 1 to 31, both sides
    LP->>LP: ItemStack.onUseTick, five particles every fourth tick and the chew sound
    SP->>SP: the same call, particles discarded, sound broadcast to everyone else
    Note over MC,Cons: tick 32, the count reaching zero on the server alone
    SP->>Wire: ClientboundEntityEventPacket, EntityEvent.USE_ITEM_COMPLETE
    SP->>Cons: ItemStack.finishUsingItem, Consumable.onConsume, FoodData.eat
    Wire->>LP: Player.handleEntityEvent replays completeUsingItem locally
    SP->>Wire: ClientboundSetHealthPacket, same tick, overwrites the prediction
    Note over MC,Cons: a later tick
    SP->>Wire: broadcastChanges corrects the stack count

The replay is the interesting half. Consumable.onConsume runs on both sides and three parts of it do not: the Stats.ITEM_USED award and CriteriaTriggers.CONSUME_ITEM need a ServerPlayer, the ConsumeEffects in Consumable.onConsumeEffects sit behind a server-side guard, and GameEvent.EAT is a no-op because ClientLevel.gameEvent has an empty body. Particles, sound, the ConsumableListener walk that finds FoodProperties, and the ItemStack.consume shrink all run on both — and every one of those client mutations is then overwritten. That is why a chorus fruit’s teleport is never predicted while the hunger bar’s jump is (hunger and experience).

One meal, two exactly-once sound strategies. The chew sound goes through Player.playSound, which names the eater as the entity to exclude, so the server broadcasts it to everyone else and the eater’s client plays it locally. The FoodProperties eat and burp sounds pass no exclusion at all — and ClientLevel.playSeededSound plays a sound only when the excluded entity is the local player — so those reach the eater as the server’s broadcast alone.

The bow, tick by tick

sequenceDiagram
    participant MC as Minecraft
    participant LP as LocalPlayer
    participant MPGM as MultiPlayerGameMode
    participant Wire as the network
    participant SGPL as ServerGamePacketListenerImpl
    participant SP as ServerPlayer
    participant BowI as BowItem

    Note over MC,BowI: tick 0, the press
    MC->>MPGM: startUseItem, nothing under the crosshair
    MPGM->>BowI: ItemStack.use, BowItem.use asks Player.getProjectile
    BowI->>LP: startUsingItem, remaining = 72000
    MPGM->>Wire: ServerboundUseItemPacket, hand and sequence and both rotations
    Wire->>SGPL: handleUseItem acks the sequence and snaps the rotation
    SGPL->>SP: the same BowItem.use, remaining = 72000, the two flag bits are written
    Note over MC,BowI: every tick after that, both sides
    LP->>LP: the count falls, onUseTick is empty, the model reads the use duration
    SP->>SP: the count falls, and nothing else happens at all
    Note over MC,BowI: the tick the key comes up
    MC->>MPGM: releaseUsingItem
    MPGM->>Wire: ServerboundPlayerActionPacket, RELEASE_USE_ITEM, sequence zero
    MPGM->>BowI: LivingEntity.releaseUsingItem, BowItem.releaseUsing on the client
    BowI->>LP: no ServerLevel, so no ammo and no arrow, then stopUsingItem
    Wire->>SGPL: handlePlayerAction, the rotation is whatever the server last heard
    SGPL->>SP: LivingEntity.releaseUsingItem
    SP->>BowI: BowItem.releaseUsing, ProjectileWeaponItem.draw then shoot
    BowI->>Wire: Projectile.spawnProjectile, then ClientboundAddEntityPacket
    SGPL-->>MPGM: nothing acknowledges the release itself
    Note over MC,BowI: a later tick
    SP->>Wire: the container sync corrects the arrow count and the bow's damage

BowItem.releaseUsing runs on both sides and gets nowhere on one of them. It measures the draw as BowItem.getUseDuration minus the remaining count, puts it through BowItem.getPowerForTime — a curve on the draw time in seconds, clamped at one after BowItem.MAX_DRAW_DURATION ticks — and returns false below a tenth of full power, which is why a tap of the button neither shoots nor costs durability. Above it, ProjectileWeaponItem.draw decides how many arrows leave the string (EnchantmentHelper.processProjectileCount) and ProjectileWeaponItem.useAmmo decides whether an arrow is actually spent (EnchantmentHelper.processAmmoUse). Both consult a ServerLevel and fall back to one and zero otherwise, and ProjectileWeaponItem.shoot is itself inside a ServerLevel test — so on the client the draw produces a single phantom arrow marked DataComponents.INTANGIBLE_PROJECTILE, spends nothing and shoots nothing.

On the server it is five enchantment hooks and one ordering worth remembering. EnchantmentHelper.processProjectileSpread fans a multishot volley, and each arrow is aimed by BowItem.shootProjectile through Projectile.shootFromRotation using the server’s rotation — which the release packet never updated, so the shot goes where the last movement packet said you were looking. Projectile.spawnProjectile aims, adds the entity to the level, and only afterwards calls Projectile.applyOnProjectileSpawned, which runs EnchantmentHelper.onProjectileSpawned twice when ammo and weapon are different items: once for the arrow’s stack and once for the bow’s. ItemStack.hurtAndBreak takes the durability after each arrow, and the volley breaks off if the bow dies mid-flight.

Only when Item.releaseUsing returns true does ItemStack.releaseUsing run ItemStack.applyAfterUseComponentSideEffects — the same private step ItemStack.finishUsingItem runs for the meal, converting DataComponents.USE_REMAINDER into the empty bowl and starting DataComponents.USE_COOLDOWN. (For an instant use it runs from ItemStack.use instead, and only for a zero-duration success.) Cooldowns are grouped rather than per-item: ItemCooldowns.getCooldownGroup returns UseCooldown.cooldownGroup when the component names one and the item’s Identifier otherwise, both sides own an ItemCooldowns — the client’s is a real prediction, consulted before it will even attempt a use — and ServerItemCooldowns.onCooldownStarted mirrors the server’s as one ClientboundCooldownPacket naming a group.

What the ending never carries

The release is the least-answered packet in the pipeline. ServerGamePacketListenerImpl.handlePlayerAction treats ServerboundPlayerActionPacket.Action.RELEASE_USE_ITEM in one line — call LivingEntity.releaseUsingItem, return — with no ack, no sequence number consumed, not even a spectator check. Everything the client learns about its own shot arrives as ordinary world traffic. The arrow is the quick one: adding it to the level starts its tracking inside the same call, so the spawn packet leaves on that tick. The spent ammo and the bow’s damage wait for a container slot update (containers and menus) and the cleared using-flag for entity data it has already acted on, both a tick or more later. The shoot sound is broadcast with no exclusion, so — by the same rule as the burp — the shooter hears the server’s copy and never their own.

The completion is barely richer. There is no you ate this packet: event 9 tells the client to re-derive the outcome from components it already holds, and ClientboundSetHealthPacket corrects whatever it got wrong. The single override of Item.finishUsingItem in the whole tree is SpyglassItem.finishUsingItem, which plays a sound — the spyglass being the one item whose completion is worth a sound of its own — reached either at its 1200-tick duration or, like any use, the moment you let go.

Where to look

Minecraft.handleKeybinds · Minecraft.startUseItem · MultiPlayerGameMode.useItem · MultiPlayerGameMode.releaseUsingItem · ServerGamePacketListenerImpl.handleUseItem · ServerGamePacketListenerImpl.handlePlayerAction · ServerPlayerGameMode.useItem · ItemStack.use · Item.use · LivingEntity.startUsingItem · LivingEntity.updatingUsingItem · LivingEntity.updateUsingItem · LivingEntity.completeUsingItem · LivingEntity.releaseUsingItem · ItemStack.releaseUsing · ItemStack.useOnRelease · Consumable · UseEffects · UseCooldown · BowItem · CrossbowItem · TridentItem · ProjectileWeaponItem · SpyglassItem · ItemInHandRenderer · UseDuration


Rules: names, never code · how the system works, not how the code reads · newest version only · every backticked name passes tools/verify_names.py.