User Tools

Site Tools


ru:tutorial:events

This is an old revision of the document!


Пользовательские события(ивенты)

Fabric API предоставляет систему, которая позволяет модам реагировать на события, происходящие в игре. События - это перехватчики, которые удовлетворяют общим случаям использования и/или обеспечивают повышенную совместимость и производительность между модами, которые подключаются к одним и тем же областям кода. Использование событий часто заменяет использование миксинов. Fabric API предоставляет события для важных областей в кодовой базе Minecraft, в которых могут быть заинтересованы несколько моддеров. В некоторых областях нет хуков, поэтому вы можете выбрать использование миксина или создать свое собственное событие.

В этом туториале мы рассмотрим создание события, которое запускается при стрижке овец. Процесс создания события заключается в:

  • создание интерфейса обратного вызова события
  • запуск события из миксина
  • создание тестовой реализации

Создание интерфейса обратного вызова

Интерфейс обратного вызова описывает, что должно быть реализовано слушателями событий, которые будут прослушивать ваше событие. Интерфейс обратного вызова также описывает, как событие будет вызываться из нашего миксина. Обычно объект события помещается в качестве поля в интерфейсе обратного вызова, который будет идентифицировать наше фактическое событие.

Для нашей реализации события мы выберем использовать событие с поддержкой массива. Массив будет содержать все прослушиватели событий, которые прослушивают событие. Наша реализация будет вызывать прослушиватели событий по порядку до тех пор, пока один из них не вернет ActionResult.PASS. то означает, что слушатель может сказать “отменить это”, “одобрить это” или “мне все равно, оставьте это следующему слушателю событий”, используя его возвращаемое значение. Использование ActionResult в качестве возвращаемого значения - это обычный способ заставить обработчик событий взаимодействовать таким образом.

Вам нужно будет создать интерфейс, который имеет экземпляр Event и метод для реализации ответа. Базовая настройка для нашего обратного вызова стрижки овец - это:

  1. public interface SheepShearCallback {
  2.  
  3. Event<SheepShearCallback> EVENT = EventFactory.createArrayBacked(SheepShearCallback.class,
  4. (listeners) -> (player, sheep) -> {
  5. for (SheepShearCallback listener : listeners) {
  6. ActionResult result = listener.interact(player, sheep);
  7.  
  8. if(result != ActionResult.PASS) {
  9. return result;
  10. }
  11. }
  12.  
  13. return ActionResult.PASS;
  14. });
  15.  
  16. ActionResult interact(PlayerEntity player, SheepEntity sheep);
  17. }

Давайте рассмотрим это более подробно. Когда вызывается вызывающий, мы перебираем всех слушателей:

(listeners) -> (player, sheep) -> {
    for (SheepShearCallback listener : listeners) {

Затем мы вызываем наш метод (в данном случае interact) для слушателя, чтобы получить его ответ:

ActionResult result = listener.interact(player, sheep);

Если слушатель говорит, что мы должны отменить (ActionResult.FAIL) или полностью завершить (ActionResult.SUCCESS), обратный вызов возвращает результат и завершает цикл. ActionResult.PASS переходит к следующему слушателю и в большинстве случаев должно привести к успеху, если больше не зарегистрировано слушателей:

// ....
    if(result != ActionResult.PASS) {
        return result;
    }
}
 
return ActionResult.PASS;

В Fabric API, мы добавляем комментарии Javadoc в начало классов обратного вызова, чтобы документировать, что делает каждый ActionResult. В нашем случае это может быть:

/**
 * Callback for shearing a sheep.
 * Called before the sheep is sheared, items are dropped, and items are damaged.
 * Upon return:
 * - SUCCESS cancels further processing and continues with normal shearing behavior.
 * - PASS falls back to further processing and defaults to SUCCESS if no other listeners are available
 * - FAIL cancels further processing and does not shear the sheep.
/**

Запуск события из миксина

Теперь у нас есть базовый скелет события, но нам нужно его запустить. Поскольку мы хотим, чтобы событие вызывалось, когда игрок пытается подстричь овцу, мы вызываем средство вызова события в SheepEntity#interactMob when dropItems() is called (ie. sheep can be sheared and player is holding shears):

@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();
        }
    }
}

In this simple mixin, we call the event invoker (SheepShearCallback.EVENT.invoker().[…]), which then calls all active listeners to see what it should do. It returns an ActionResult based on this, and if the result is FAIL, we don't shear the sheep, drop items, or damage the player's item (info.cancel();). Make sure to register your mixin in your mixins.json file!

Testing Event with a Listener

Now we need to test our event. You can register a listener in your initialization method (or other areas if you prefer) and add custom logic there. Here's an example that drops a diamond instead of wool at the sheep's feet:

SheepShearCallback.EVENT.register((player, sheep) -> {
    sheep.setSheared(true);
 
    // create diamond item entity at sheep position
    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;
});

Note that this event also sets the sheep to be sheared manually, as it is normally canceled if we return FAIL. If you don't need to cancel the event, make sure you return PASS so other listeners are allowed to operate as well. Failing to follow these “not spoken rules” may result in angry modders on your doorstep.

If you enter into your game and shear a sheep, a diamond should drop instead of wool.

ru/tutorial/events.1647103532.txt.gz · Last modified: 2022/03/12 16:45 by furnygo