Try   HackMD

Note on InteractionResult

  • consume implies one of SUCCESS, SUCCESS_NO_ITEM_USED, CONSUME, CONSUME_PARTIAL
  • swing implies one of SUCCESS, SUCCESS_NO_ITEM_USED

The current interaction events

  • LivingEntityUseItemEvent - not abstract⚠:

    • Start - LivingEntity#startUsingItem - C, fired in LivingEntity#startUsingItem, can modify the use duration (or cancel with a value < 0)
    • Tick - LivingEntity#updateUsingItem:
      • we have a patch for IItemExtension#canContinueUsing, that provides more control over whether items can still be used, even after having been changed
      • event fired in LivingEntity#updateUsingItem, only allows changing the remaining duration (or cancelling -> -1, triggering a completion)
      • does not allow preventing Item#onUseTick from being called, unless the reamining ticks are set to 0 or less, which also causes completion
    • Stop - LivingEntity#releaseUsingItem - C, fired before Item#releaseUsing and EH#onPlayerDestroyItem; does not affect Item#useOnRelease (which may trigger another use, in the case of crossbows)
    • Finish - LivingEntity#completeUsingItem - NC, can change result stack, but fired after triggerItemUseEffects (sounds); if changed, calls setItemInHand, but the useItem isn't changed so Item#onStopUsing is still called on the original item in stopUsingItem
  • ArrowNockEvent - ⚠ pls remove; C, fired in BowItem#use, provides player.getProjectile(itemstack).isEmpty() over any other interaction events. If cancelled, or with a non-null InteractionResultHolder, it will exit with it.

  • FillBucketEvent - C, fired in BucketItem#use early, if cancelled it will FAIL the interaction, can modify the result item stack

  • PlayerInteractEvent - brace yourselves:

    • EntityInteractSpecific - C, earliest, fired in
      • ServerGamePacketListenerImpl$handleInteract$onInteraction, a cancellation result will prevent Entity#interactAt; a consumed action will trigger PLAYER_INTERACTED_WITH_ENTITY, and a success will also triger a swing
      • on the clientside, fired in MultiPlayerGameMode#interactAt, after the packet was sent, and after spectator checks; a cancellation result will prevent Entity#interactAt; if consumed, item, block or Entity#interact interactions will be aborted; swing is triggered by a success AND the InteractionKeyMappingTriggered event setting shouldSwingHand (true by default), which always takes effect, regardless of cancellation
    • EntityInteract - C, fired in Player#interactOn, but not when in spectator as that only allows opening menu entities; triggered only if interactAt (see above) is NOT consumed; result implies:
      • server side: PLAYER_INTERACTED_WITH_ENTITY if consumed, swing if success
      • client side: same effect as above
    • RightClickBlock - C, after entity interactions, fired in:
      • server side: SPGM#useItemOn, success triggering swing, consume triggering ANY_BLOCK_USE
      • client side: MPGM#performUseItemOn, will stil send packet to the server; consumed action prevents further item interaction, success action and InteractionKeyMappingTriggered#shouldSwingHand implies a swing, with a client-side use item animation if on creative or item count has decreased;
      • common, if not cancelled:
        • a non-deny of useItem will call ItemStack#onItemUseFirst (triggering ITEM_BEFORE_BLOCK@UseItemOnBlockEvent)
        • explicit ALLOW or DEFAULT with met conditions (!(doesSneakBypassUse && isSecondaryUseActive)) will proceed to call Block#useItemOn (which fires BLOCK@UseItemOnBlockEvent):
          • a consumed result will have the effects described above, triggering ITEM_USED_ON_BLOCK
          • ItemInteractionResult#PASS_TO_DEFAULT_BLOCK_INTERACTION and main hand will trigger Block#useWithoutItem, and a consumed result will have the effects described above, triggering DEFAULT_BLOCK_USE
        • DENY of useItem will return InteractionResult.PASS
        • ALLOW / DEFAULT (stack not empty or not on cooldown) and conditions met of useItem will trigger Item#useOn (firing ITEM_AFTER_BLOCK@UseItemOnBlockEvent, with effects described above, and triggering ITEM_USED_ON_BLOCK (creative will restore the count)
        • otherwise, returns InteractionResult.PASS
          RightClickEmpty - NC, after block interactions, ONLY ON THE CLIENT, if use stack is empty and interaction was a miss (no block, no entity, i.e. "empty space")
    • RightClickItem - C, after block interactions, if use stack is not empty:
      • server side: SPGM#useItem, success triggering swing; only fired after cooldown and spectator checks, before Item#use
      • client side: MPGM#useItem, after the cooldown check, before Item#use, cancellation does not prevent packet; consumed action triggers client-side use animation, success triggers swing
    • LeftClickBlock - C, fired when a block is left clicked:
      • server side: SPGM#handleBlockBreakAction (triggered by START_DESTROY_BLOCK, ABORT_DESTROY_BLOCK, STOP_DESTROY_BLOCK), cancelled event or DENY in survival mode prevents further processing;
        • START_DESTROY_BLOCK: if useBlock is not DENY, Block#attack will be called
      • client side: MPGM#startDestroyBlock:
        • creative mode: fires as START_DESTROY_BLOCK, if cancelled, block will not be broken (but packet sent)
        • if the player has already started destroying, and continues to in this interaction, fires as CLIENT_HOLD, and a DENY of useItem prevents the block from actually being destroyed, but does not prevent destruction progress from being incremented
        • if the player starts destroying a new block, fires as START_DESTROY_BLOCK; useBlock of DENY prevents Block#attack from being called; useItem of DENY prevents destruction from starting
    • LeftClickEmpty - NC, last punch action, fired only if the left click was a miss (i.e. "empty space"), with a 10 tick cooldown

Client-side events

  • InputEvent.InteractionKeyMappingTriggered:
    • triggers with 0 as left click, cancellation prevents destruction (progress)
    • triggers with 1 as right click, cancellation prevents entity/block/item/empty interactions
    • triggers with 2 as pick block, cancellation prevents the block from being picked, no swing

Issues found

In SPGM#useItemOn, useItem == DENY -> PASS is misaligned in an if