User Tools

Site Tools


zh_cn:tutorial:events

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
zh_cn:tutorial:events [2021/09/07 02:55] solidblockzh_cn:tutorial:events [2023/05/04 11:13] solidblock
Line 2: Line 2:
 ** FIXME 本页翻译自 [[tutorial:events]],翻译需要完善。** ** FIXME 本页翻译自 [[tutorial:events]],翻译需要完善。**
  
-Fabric API 提供一个允许模组对游戏内事件作出反应的系统。事件常见用例和是/或者在钩到代码相同区域的模组之间提供增强兼容性性能的钩子。事件的使用通常代替 mixin 的使用 +Fabric API 提供一个允许模组对游戏内事件作出反应的系统。事件(events)是满足常见用例的钩子(hooks),同时也能在钩到代码相同区域的模组之间增强兼容性、改善性能。使用事件通常就能代替 mixin。Fabric API 为 Minecraft 代码库中的重要区域提供了事件,模组作就会需钩到这些钩子。有些地方是没有钩子的,所以你可以选择使用 mixin,或创建你自己的事件。
-Fabric API 为 Minecraft 代码库中的重要区域提供了事件,多个修改可能想钩子。有些地方是没有钩子的,所以你可以选择使用 mixin,或创建你自己的事件。+
  
 在本教程中,我们将着眼于创建一个在剪羊毛时触发的事件。创建事件的过程是: 在本教程中,我们将着眼于创建一个在剪羊毛时触发的事件。创建事件的过程是:
-  * 创建事件回调接口+  * 创建事件回调接口(event callback interface)
   * 从 mixin 触发事件   * 从 mixin 触发事件
   * 创建一个测试实现   * 创建一个测试实现
 +
 +==== 创建回调接口 ====
 +回调接口是最需要由监听事件的事件监听器实现的,事件也会从 mixin 中通过回调接口被调用。在回调接口中,必须放置一个 Event 对象作为字段,以识别实际事件。
 +
 +对于事件实现,我们选择使用由数组支持的事件。这个数组会包含所有监听事件的事件监听器。我们的实现会依次调用事件监听器,直到其中一个不再返回 ''ActionResult.PASS'',这意味着,监听器可能会使用其返回值来要求“退出这个”、“批准这个”或者“不用在意,留给下一个事件监听器”。这种返回一个 ActionResult 值的方法,通常能够使得事件监听器能够合作。
 +
 +你需要创建一个包含 ''Event'' 实例的接口,接口需包含用于响应实现的方法。剪羊毛事件回调的基本步骤为:
 +
 +<code java [enable_line_numbers="true"]>
 +public interface SheepShearCallback {
 +
 +    Event<SheepShearCallback> EVENT = EventFactory.createArrayBacked(SheepShearCallback.class,
 +        (listeners) -> (player, sheep) -> {
 +            for (SheepShearCallback listener : listeners) {
 +                ActionResult result = listener.interact(player, sheep);
 +                
 +                if(result != ActionResult.PASS) {
 +                    return result;
 +                }
 +            }
 +
 +        return ActionResult.PASS;
 +    });
 +
 +    ActionResult interact(PlayerEntity player, SheepEntity sheep);
 +}
 +</code>
 +
 +现在再深入一点,调用了这个调用器(invoker)时,迭代所有的监听器:
 +<code java [enable_line_numbers="false"]>
 +(listeners) -> (player, sheep) -> {
 +    for (SheepShearCallback listener : listeners) {
 +</code>
 +然后在监听器中调用我们的方法(本例中,为 ''interact'')以获得响应:
 +<code java [enable_line_numbers="false"]>
 +ActionResult result = listener.interact(player, sheep);
 +</code>
 +如果监听器告知我们需要退出(''ActionResult.FAIL'')或者彻底完成(''ActionResult.SUCCESS''),回调则会返回结果并完成循环。''ActionResult.PASS'' 会移到下一个监听器,大多数情况下,如果没有再注册更多监听器,则一般会以成功结束。
 +<code java [enable_line_numbers="false"]>
 +// ....
 +    if(result != ActionResult.PASS) {
 +        return result;
 +    }
 +}
 +
 +return ActionResult.PASS;
 +</code>
 +
 +在 [[https://github.com/FabricMC/fabric|Fabric API]] 中,我们在回调类的顶部添加 Javadoc 注释,以阐明每个 ActionResult 所做了什么。在我们的例子中,可能是:
 +<code java [enable_line_numbers="false"]>
 +/**
 + * 剪羊毛时的回调。
 + * 剪羊毛并掉落物品、物品被损害之前调用。
 + * 会返回:
 + * - SUCCESS 退出后续处理过程,然后继续进行正常剪羊毛行为。
 + * - PASS 回落到后续处理过程,如果没有其他的监听器了,则默认为 SUCCESS。
 + * - FAIL 退出后续处理过程,羊毛不会被剪掉。
 +/**
 +</code>
 +
 +==== 从 Mixin 中触发事件 ====
 +我们有了基本的事件框架,但我们还需要触发它。由于我们需要让事件在玩家尝试剪羊毛时调用,我们在 ''SheepEntity#interactMod'' 中,当 ''dropItems'' 调用的时候(即羊可以被剪且玩家拿着剪刀),调用事件调用器。
 +<code java [enable_line_numbers="false"]>
 +@Mixin(SheepEntity.class)
 +public class SheepShearMixin {
 +
 +    @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/SheepEntity;dropItems()V"), method = "interactMob", cancellable = true)
 +    private void onShear(final PlayerEntity player, final Hand hand, final CallbackInfoReturnable<Boolean> info) {
 +        ActionResult result = SheepShearCallback.EVENT.invoker().interact(player, (SheepEntity) (Object) this);
 +        
 +        if(result == ActionResult.FAIL) {
 +            info.cancel();
 +        }
 +    }
 +}
 +</code>
 +在这个简单的 mixin 中,我们调用了事件的调用器(''SheepShearCallback.EVENT.invoker().[...]''),它会调用所有活动的监听器来看看应该做什么,然后根据这个招架一个 ActionResult。如果结果为 FAIL,我们不剪羊毛、掉落物品或者损害玩家的物品(''info.cancel();'')。**确保你在 mixins.json 文件中注册的这个 mixin!**
 +
 +==== 使用监听器测试事件 ====
 +我们需要测试我们的事件。你可以在你的初始化方法(或者你需要的其他任何地方)注册一个监听器并在这里添加自定义的逻辑。这里是一个示例,会在绵羊的腿的位置掉落钻石而非羊毛:
 +<code java [enable_line_numbers="false"]>
 +SheepShearCallback.EVENT.register((player, sheep) -> {
 +    sheep.setSheared(true);
 +
 +    // 在绵羊的位置妴钻石
 +    ItemStack stack = new ItemStack(Items.DIAMOND);
 +    ItemEntity itemEntity = new ItemEntity(player.world, sheep.x, sheep.y, sheep.z, stack);
 +    player.world.spawnEntity(itemEntity);
 +
 +    return ActionResult.FAIL;
 +});
 +</code>
 +注意这个事件还需要设置羊被手动剪,就像在返回 FAIL 的时候自动取消。我们你//不需要//取消这个事件,确保你返回了 ''PASS'' 从而其他的监听器也可以操作。如果不遵守这个不成文规则,可能影响其他模组开发者对此模组的兼容性。
 +
 +如果你进入游戏并给绵羊剪羊毛,掉落的就会是钻石而不是羊毛。
 +
zh_cn/tutorial/events.txt · Last modified: 2023/05/04 11:13 by solidblock