Interactions
This page aims to make the fairly complex and confusing process of things being left-clicked, right-clicked or middle-clicked by the player more understandable, as well as clarifying what result to use where and why.
HitResults
For the purpose of determining what the player is currently looking at, Minecraft uses a HitResult. A HitResult is somewhat equivalent to a ray cast result in other game engines, and most notably contains a method #getLocation.
A hit result can be of one of three types, represented through the HitResult.Type enum: BLOCK, ENTITY, or MISS. A HitResult of type BLOCK can be cast to BlockHitResult, while a HitResult of type ENTITY can be cast to EntityHitResult; both types provide additional context about what block or entity was hit. If the type is MISS, this indicates that neither a block nor an entity was hit, and should not be cast to either subclass.
Every frame on the physical client, the Minecraft class updates and stores the currently looked-at HitResult in the hitResult field. This field can then be accessed through Minecraft.getInstance().hitResult.
Left-Clicking an Item
- It is checked that all required feature flags for the
ItemStackin your main hand are enabled. If this check fails, the pipeline ends. InputEvent.InteractionKeyMappingTriggeredis fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends.- Depending on what you are looking at (using the
HitResultinMinecraft), different things happen:- If you are looking at an entity that is within your reach:
AttackEntityEventis fired. If the event is canceled, the pipeline ends.IItemExtension#onLeftClickEntityis called. If it returns true, the pipeline ends.Entity#isAttackableis called on the target. If it returns false, the pipeline ends.Entity#skipAttackInteractionis called on the target. If it returns true, the pipeline ends.- If the target is in the
minecraft:redirectable_projectiletag (by default this is fireballs and wind charges) and an instance ofProjectile, the target is deflected and the pipeline ends. - Entity base damage (the value of the
minecraft:generic.attack_damageattribute) and enchantment bonus damage are calculated as two separate floats. If both are 0, the pipeline ends.- Note that this excludes attribute modifiers from the main hand item, these are added after the check.
minecraft:generic.attack_damageattribute modifiers from the main hand item are added to the base damage.CriticalHitEventis fired. If the event's#isCriticalHitmethod returns true, the base damage is multiplied with the value returned from the event's#getDamageMultipliermethod, which defaults to 1.5 if a number of conditions pass and 1.0 otherwise, but may be modified by the event.- Enchantment bonus damage is added to the base damage, resulting in the final damage value.
SweepAttackEventis fired. If the event'sisSweepingmethod returns true, then the player will perform a sweep attack. By default, this checks if the attack cooldown is > 90%, the attack is not a critical hit, the player is on the ground and not moving faster than theirminecraft:generic.movement_speedattribute value.Entity#hurtOrSimulateis called. If it returns false, the pipeline ends.- If the target is an instance of
LivingEntityand the attack strength is greater than 90%, the player is sprinting, and theminecraft:attack_knockbackattribute value after being modified by enchantments is greater than 0,LivingEntity#knockbackis called.- Within that method,
LivingKnockBackEventis fired.
- Within that method,
- The player performs a sweep attack on nearby
LivingEntitys based onSweepAttackEvent#isSweeping.- Within that method,
LivingEntity#knockbackis called again if the entity is in reach of the player andEntity#hurtServerreturns true, which in turn firesLivingKnockBackEventanother time.
- Within that method,
Item#hurtEnemyis called. This can be used for post-attack effects. For example, the mace launches the player back in the air here, if applicable.Item#postHurtEnemyis called. Durability damage is applied here.
- If you are looking at a block that is within your reach:
- The block breaking sub-pipeline is initiated.
- Otherwise:
PlayerInteractEvent.LeftClickEmptyis fired.
- If you are looking at an entity that is within your reach:
Right-Clicking an Item
During the right-clicking pipeline, a number of methods returning one of two result types (see below) are called. Most of these methods cancel the pipeline if an explicit success or an explicit failure is returned. For the sake of readability, this "explicit success or explicit failure" will be called a "definitive result" from now on.
InputEvent.InteractionKeyMappingTriggeredis fired with the right mouse button and the main hand. If the event is canceled, the pipeline ends.- Several circumstances are checked, for example that you are not in spectator mode or that all required feature flags for the
ItemStackin your main hand are enabled. If at least one of these checks fails, the pipeline ends. - Depending on what you are looking at (using the
HitResultinMinecraft), different things happen:- If you are looking at an entity that is within your reach and not outside the world border:
PlayerInteractEvent.EntityInteractSpecificis fired. If the event is canceled, the pipeline ends.Entity#interactAtwill be called on the entity you are looking at. If it returns a definitive result, the pipeline ends.- If you want to add behavior for your own entity, override this method. If you want to add behavior for a vanilla entity, use the event.
- If the entity opens an interface (for example a villager trading GUI or a chest minecart GUI), the pipeline ends.
PlayerInteractEvent.EntityInteractis fired. If the event is canceled, the pipeline ends.Entity#interactis called on the entity you are looking at. If it returns a definitive result, the pipeline ends.- If you want to add behavior for your own entity, override this method. If you want to add behavior for a vanilla entity, use the event.
- For
Mobs, the override ofEntity#interacthandles things like leashing and spawning babies when theItemStackin your main hand is a spawn egg, and then defers mob-specific handling toMob#mobInteract. The rules for results forEntity#interactapply here as well.
- If the entity you are looking at is a
LivingEntity,Item#interactLivingEntityis called on theItemStackin your main hand. If it returns a definitive result, the pipeline ends.
- If you are looking at a block that is within your reach and not outside the world border:
PlayerInteractEvent.RightClickBlockis fired. If the event is canceled, the pipeline ends. You may also specifically deny only block or item usage in this event.IItemExtension#onItemUseFirstis called. If it returns a definitive result, the pipeline ends.- If the player is not sneaking and the event does not deny block usage,
UseItemOnBlockEventis fired. If the event is canceled, the cancellation result is used. Otherwise,BlockBehaviour#useItemOnis called. If it returns a definitive result, the pipeline ends. - If the
InteractionResultisTRY_WITH_EMPTY_HANDand the executing hand is the main hand, thenBlockBehaviour#useWithoutItemis called. If it returns a definitive result, the pipeline ends. - If the event does not deny item usage,
Item#useOnis called. If it returns a definitive result, the pipeline ends.
- If you are looking at an entity that is within your reach and not outside the world border:
Item#useis called. If it returns a definitive result, the pipeline ends.- The above process runs a second time, this time with the off hand instead of the main hand.
InteractionResult
InteractionResult is a sealed interface that represents the result of some interaction between an item or an empty hand and some object (e.g. entities, blocks, etc.). The interface is broken into four records, where there are six potential default states.
First there is InteractionResult.Success, which indicates that the operation should be considered successful, ending the pipeline. A successful state has two parameters: the SwingSource, which indicates whether the entity should swing on the respective logical side; and the InteractionResult.ItemContext, which holds whether the interaction was caused by a held item, and what the held item transformed into after use. The swing source is determined by one of the default states: InteractionResult#SUCCESS for client swing, InteractionResult#SUCCESS_SERVER for server swing, and InteractionResult#CONSUME for no swing. The item context is set via Success#heldItemTransformedTo if the ItemStack changed, or withoutItem if there wasn't an interaction between the held item and the object. The default sets there was an item interaction but no transformation.
// In some method that returns an interaction result
// Item in hand will turn into an apple
return InteractionResult.SUCCESS.heldItemTransformedTo(new ItemStack(Items.APPLE));
SUCCESS and SUCCESS_SERVER should generally never be used in the same method. If the client has enough information to determine when to swing, then SUCCESS should always be used. Otherwise, if it relies on server information not present on the client, SUCCESS_SERVER should be used.
Then there is InteractionResult.Fail, implemented by InteractionResult#FAIL, which indicates that the operation should be considered failed, allowing no further interaction to occur. The pipeline will end. This can be used anywhere, but it should be used with care outside of Item#useOn and Item#use. In many cases, using InteractionResult#PASS makes more sense.
Finally, there is InteractionResult.Pass and InteractionResult.TryWithEmptyHandInteraction, implemented by InteractionResult#PASS and InteractionResult#TRY_WITH_EMPTY_HAND respectively. These records indicate when an operation should be considered neither successful or failed, and the pipeline should continue. PASS is the default behavior for all InteractionResult methods except BlockBehaviour#useItemOn, which returns TRY_WITH_EMPTY_HAND. More specifically, if BlockBehaviour#useItemOn returns anything but TRY_WITH_EMPTY_HAND, BlockBehaviour#useWithoutItem will not be called regardless of if the item is in the main hand.
Some methods have special behavior or requirements, which are explained in the below chapters.
Item#useOn
If you want the operation to be considered successful, but you do not want the arm to swing or an ITEM_USED stat point to be awarded, use InteractionResult#CONSUME and calling #withoutItem.
// In Item#useOn
return InteractionResult.CONSUME.withoutItem();
Item#use
This is the only instance where the transformed ItemStack is used from a Success variant (SUCCESS, SUCCESS_SERVER, CONSUME). The resulting ItemStack set by Success#heldItemTransformedTo replaces the ItemStack the usage was initiated with, if it has changed.
The default implementation of Item#use returns InteractionResult#CONSUME when the item is edible (has DataComponents#CONSUMABLE) and the player can eat the item (because they are hungry, or because the item is always edible) and InteractionResult#FAIL when the item is edible (has DataComponents#CONSUMABLE) but the player cannot eat the item. If the item is equippable (has DataComponents#EQUIPPABLE), then it returns InteractionResult#SUCCESS on swap with the held item replaced by the swapped item (via heldItemTransformedTo), or InteractionResult#FAIL if the enchantment on the armor has the EnchantmentEffectComponents#PREVENT_ARMOR_CHANGE component. Otherwise InteractionResult#PASS is returned.
Returning InteractionResult#FAIL here while considering the main hand will prevent offhand behavior from running. If you want offhand behavior to run (which you usually want), return InteractionResult#PASS instead.
Middle-Clicking
- If the
HitResultinMinecraft.getInstance().hitResultis null or of typeMISS, the pipeline ends. InputEvent.InteractionKeyMappingTriggeredis fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends.- Depending on what you are looking at (using the
HitResultinMinecraft.getInstance().hitResult), different things happen:- If you are looking at an entity that is within your reach:
- If
Entity#isPickablereturns false, the pipeline ends. - If
Player#canInteractWithEntityreturns false, the pipeline ends. Entity#getPickResultis called. A hotbar slot that matches the resultingItemStackis set active, if such a hotbar slot exists. Otherwise, if the player is in creative, the resultingItemStackis added to the player's inventory.- By default, this method forwards to
Entity#getPickResult, which can be overridden by modders.
- By default, this method forwards to
- If
- If you are looking at a block that is within your reach:
IBlockExtension#getCloneItemStackis called (which by default delegates toBlockBehaviour#getCloneItemStack) and becomes the "selected"ItemStack.- By default, this returns the
Itemrepresentation of theBlock.
- By default, this returns the
- If the Control key is held down, the player is in creative and the targeted block has a
BlockEntity:- The
BlockEntity's data is obtained fromBlockEntity#saveCustomOnlyBlockEntity#removeComponentsFromTagis called as a post processing step.
- The
BlockEntity's data is added to the "selected"ItemStackviaDataComponents#BLOCK_ENTITY_DATA.
- The
- A hotbar slot that matches the "selected"
ItemStackis set active, if such a hotbar slot exists. Otherwise, if the player is in creative, the "selected"ItemStackis added to the player's inventory.
- If you are looking at an entity that is within your reach: