交互
交互流程
本页旨在使玩家右键点击时发生的相当复杂和令人困惑的过程更加易于理解,并阐明在何处以及为何使用哪种结果。
当我右键点击时会发生什么?
当您在世界上任何地方右键点击时,会发生一系列事情,具体取决于您当前正在查看的内容以及您手中的 ItemStack。许多方法会返回两种结果类型之一(见下文)。如果返回明确成功或明确失败,大多数这些方法会取消流程。为了可读性,从现在开始,这种“明确成功或明确失败”将被称为“明确结果”。
- 使用右键和主手触发
InputEvent.InteractionKeyMappingTriggered。如果事件被取消,流程结束。 - 检查几种情况,例如您是否处于旁观模式或主手中的
ItemStack是否启用了所有必需的功能标志。如果至少有一个检查失败,流程结束。 - 根据您正在查看的内容,会发生不同的事情:
- 如果您正在查看一个实体,并且该实体在您的触及范围内且不在世界边界之外:
- 触发
PlayerInteractEvent.EntityInteractSpecific。如果事件被取消,流程结束。 - 在您正在查看的实体上调用
Entity#interactAt。如果它返回明确结果,流程结束。- 如果您想为自己的实体添加行为,请重写此方法。如果您想为原版实体添加行为,请使用事件。
- 如果实体打开了一个界面(例如村民交易 GUI 或箱子矿车 GUI),流程结束。
- 触发
PlayerInteractEvent.EntityInteract。如果事件被取消,流程结束。 - 在您正在查看的实体上调用
Entity#interact。如果它返回明确结果,流程结束。- 如果您想为自己的实体添加行为,请重写此方法。如果您想为原版实体添加行为,请使用事件。
- 对于生物,
Entity#interact的重写处理诸如当主手中的ItemStack是刷怪蛋时的拴绳和生成幼崽等事情,然后将生物特定的处理推迟到Mob#mobInteract。Entity#interact的结果规则在此同样适用。 - 如果您正在查看的实体是
LivingEntity,则在主手中的ItemStack上调用Item#interactLivingEntity。如果它返回明确结果,流程结束。
- 触发
- 如果您正在查看一个方块,并且该方块在您的触及范围内且不在世界边界之外:
- 触发
PlayerInteractEvent.RightClickBlock。如果事件被取消,流程结束。您也可以在此事件中专门拒绝方块或物品的使用。 - 调用
IItemExtension#onItemUseFirst。如果它返回明确结果,流程结束。 - 如果玩家没有潜行且事件没有拒绝方块使用,则触发
UseItemOnBlockEvent。如果事件被取消,则使用取消结果。否则,调用Block#useItemOn。如果它返回明确结果,流程结束。 - 如果
ItemInteractionResult是PASS_TO_DEFAULT_BLOCK_INTERACTION并且执行的手是主手,则调用Block#useWithoutItem。如果它返回明确结果,流程结束。 - 如果事件没有拒绝物品使用,则调用
Item#useOn。如果它返回明确结果,流程结束。 - 调用
Item#use。如果它返回明确结果,流程结束。
- 触发
- 如果您正在查看一个实体,并且该实体在您的触及范围内且不在世界边界之外:
- 上述过程会再次运行,这次使用副手而不是主手。
结果类型
有三种不同的结果类型:InteractionResult、ItemInteractionResult 和 InteractionResultHolder<T>。大多数情况下使用 InteractionResult,只有 Item#use 使用 InteractionResultHolder<ItemStack>,只有 BlockBehaviour#useItemOn 和 CauldronInteraction#interact 使用 ItemInteractionResult。
InteractionResult 是一个枚举,由五个值组成:SUCCESS、CONSUME、CONSUME_PARTIAL、PASS 和 FAIL。此外,InteractionResult#sidedSuccess 方法可用,它在服务器上返回 SUCCESS,在客户端上返回 CONSUME。
InteractionResultHolder<T> 是 InteractionResult 的包装器,为 T 添加了额外的上下文。T 可以是任何东西,但在 99.99% 的情况下,它是一个 ItemStack。InteractionResultHolder<T> 提供了枚举值的包装方法(#success、#consume、#pass 和 #fail),以及 #sidedSuccess,它在服务器上调用 #success,在客户端上调用 #consume。
ItemInteractionResult 是 InteractionResult 的并行版本,专门用于在方块上使用物品时。它是一个由六个值组成的枚举:SUCCESS、CONSUME、CONSUME_PARTIAL、PASS_TO_DEFAULT_BLOCK_INTERACTION、SKIP_DEFAULT_BLOCK_INTERACTION 和 FAIL。每个 ItemInteractionResult 都可以通过 #result 映射到 InteractionResult;PASS_TO_DEFAULT_BLOCK_INTERACTION 和 SKIP_DEFAULT_BLOCK_INTERACTION 都表示 InteractionResult#PASS。同样,#sidedSucess 也存在于 ItemInteractionResult 中。
通常,不同的值意味着以下内容:
InteractionResult#sidedSuccess(或InteractionResultHolder#sidedSuccess/ItemInteractionResult#sidedSucess,视需要而定)应用于操作应被视为成功并且您希望手臂摆动的情况。流程将结束。InteractionResult#SUCCESS(或InteractionResultHolder#success/ItemInteractionResult#SUCCESS,视需要而定)应用于操作应被视为成功并且您希望手臂摆动,但仅在一端的情况。仅在您希望出于某种原因在另一逻辑端返回不同值时才使用此方法。流程将结束。InteractionResult#CONSUME(或InteractionResultHolder#consume/ItemInteractionResult#CONSUME,视需要而定)应用于操作应被视为成功但您不希望手臂摆动的情况。流程将结束。InteractionResult#CONSUME_PARTIAL与InteractionResult#CONSUME基本相同,唯一的区别在于它在Item#useOn中的使用。ItemInteractionResult#CONSUME_PARTIAL在BlockBehaviour#useItemOn中的使用类似。InteractionResult.FAIL(或InteractionResultHolder#fail/ItemInteractionResult#FAIL,视需要而定)应用于物品功能应被视为失败且不应执行进一步交互的情况。流程将结束。这可以在任何地方使用,但在Item#useOn和Item#use之外应谨慎使用。在许多情况下,使用InteractionResult.PASS更有意义。InteractionResult.PASS(或InteractionResultHolder#pass,视需要而定)应用于操作应被视为既不成功也不失败的情况。流程将继续。这是默认行为(除非另有说明)。ItemInteractionResult#PASS_TO_DEFAULT_BLOCK_INTERACTION允许为主手调用BlockBehaviour#useWithoutItem,而#SKIP_DEFAULT_BLOCK_INTERACTION则完全阻止该方法的执行。#PASS_TO_DEFAULT_BLOCK_INTERACTION是默认行为(除非另有说明)。
某些方法具有特殊行为或要求,这些将在以下章节中解释。
IItemExtension#onItemUseFirst
InteractionResult#sidedSuccess 和 InteractionResult.CONSUME 在这里没有效果。这里只应使用 InteractionResult.SUCCESS、InteractionResult.FAIL 或 InteractionResult.PASS。
Item#useOn
如果您希望操作被视为成功,但您不希望手臂摆动或授予 ITEM_USED 统计点,请使用 InteractionResult.CONSUME_PARTIAL。
Item#use
这是唯一返回类型为 InteractionResultHolder<ItemStack> 的实例。InteractionResultHolder<ItemStack> 中的结果 ItemStack 替换了启动使用的 ItemStack,如果它已更改。
Item#use 的默认实现在物品可食用且玩家可以食用该物品(因为他们饿了,或者因为该物品始终可食用)时返回 InteractionResultHolder#consume,在物品可食用但玩家不能食用该物品时返回 InteractionResultHolder#fail,在物品不可食用时返回 InteractionResultHolder#pass。
在此处返回 InteractionResultHolder#fail 同时考虑主手将阻止副手行为运行。如果您希望副手行为运行(通常您希望如此),请改为返回 InteractionResultHolder#pass。