Как сделать свой ивент в майнкрафт

Обновлено: 05.07.2024

Решил сделать отдельную тему для моего перевода зарубежного туториала.
(моя основная тема).

Много вопросов связаны с событиями, хотел бы их урезать на корню одной темой.
Также даже бывалые моддеры может что-то полезное узнают, например, как работать с приоритетами событий.

Иностранный оригинал туториала сделал: coolAlias
Исходник урока можно найти в теме со списком всех моих уроков.
Об ошибках, вопросах и предложениях о переводе писать сюда: ВК или в ЛС этого форума.

  • Шина Событий = Event Bus
  • Обработчик Событий = Event Handler
  • Событие = Event
  • Слушатель Событий = Метод с событием в параметре и с аннотацией @ForgeSubscribe (1.6 и ранее) или @SubcribeEvent (1.7+)

Если вы хотите изменить любую стандартную реакцию Minecraft'а на какое либо действие, то применяйте обработчик событий. В нем есть События Игрока (Player Events), События Живых Существ (Living Events), События Предметов (Item Events), События Мира(World Events), Событие Генерации Мира (TerrainGenEvents), События Вагонетки (Minecart Events). и многое другое. Так что вы можете сделать что-то невероятное, применяя события. Лично я предпочитаю применять EventHandler, вместо TickHandler'а. Так как многие вещи в TickHandler'е нужно писать самостоятельно, тогда как в EventHandler'e они уже сделаны.

  1. Построении и использовании Event Handler'а
    [/*]
  2. Расширенной информации про обработку событий
    [/*]
  3. Простых событиях и их возможных применениях

ВАЖНО. Не называйте ваш обработчик событий 'EventHandler' - это название уже занято форджем. Также, ни в коем случае НЕ изменяйте классы форджа.
Вам нужно создать новый класс для обработки событий.

Регистрируйте ваш обработчик событий через EVENT_BUS в методах 'load' или 'postInit' вашего главного класса мода. Эта часть является одинаковой для 1.6 и 1.7, дополнительная информация в конце туториала.

  1. MinecraftForge.EVENT_BUS: Здесь большая часть событий.
  2. MinecraftForge.TERRAIN_GEN_BUS: Большая часть событий генерации здесь - заселение, декорирование мира. но есть странное исключение для Pre и Post событий, они находятся в EVENT_BUS
  3. MinecraftForge.ORE_GEN_BUS: Очевидно - события генерации руд здесь
  4. FML Events: Эти события очень важны в 1.7.х, т.к. там существуют события TickEvent и KeyInputEvent, которые являются заменой для TickHandler'a и KeyHandler'a в 1.6.х.

Это было легко, но пока ничего не делайте. Переходим к части 3.

Спойлер: Часть 3: Добавление событий в ваш обработчик (как пример)

Выберите нужное вам событие из MinecraftForge, и добавьте его в свой EventHandler (обработчик событий) путем создания нового метод и установки события (Event'а) в качестве параметра метода.
1.6: Используйте аннотацию "@ForgeSubscribe". Она вызывает событие в нужный момент.
1.7+: Используйте аннотацию "@SubscribeEvent". Она вызывает событие в нужный момент.

Никогда, я повторю, никогда НЕ изменяйте классы форджа. Также, вам не требуется создание класса, унаследованного от класса события.


Если вам станет интересно какие еще переменные содержит событие - напишите в методе 'event.' и Eclipse выведет вам все возможные переменные. Или просмотрите их с помощью нажатия Ctrl'a по классу события. Спойлер: Часть 4: Использование событий в ваших классах

События Форджа автоматически встраиваются в ванильный код, но скажем вы сделали свой лук и хотите использовать события ArrowNock и ArrowLoose? Вам нужно вставить их и зарегистрировать в шине событий в коде предмета.

Спойлер: Часть 5: Добавление событий в ваш EventHandler

Выберите нужное вам событие из MinecraftForge, и добавьте его в свой EventHandler (обработчик событий) путем создания нового метод и установки события (Event'а) в качестве параметра метода.
1.6: Используйте аннотацию "@ForgeSubscribe". Она вызывает событие в нужный момент.
1.7+: Используйте аннотацию "@SubscribeEvent". Она вызывает событие в нужный момент.

Никогда, я повторю, никогда НЕ изменяйте классы форджа. Также, вам не требуется создание класса, унаследованного от класса события.

Показанный шаблон подходит для любого метода с событием, который вы захотите сделать. Название метода делайте любое, но не забывайте про правильное название события. Доступ к переменным событий можно получить по примеру 'event.variableName'.

Спойлер: Продвинутая Информация: Установка приоритета

Оба метода будут вызываться по порядку регистрации в MinecraftForge.EVENT_BUS. Порядок может контролироваться добавлением (priority=VALUE) к аннотации @ForgeSubscribe, где VALUE - это один из вариантов из класса перечисления EventPriority. Приоритет HIGHEST вызывается первым, тогда как LOWEST последним.


Для нескольких модов, вызывающих одно и тоже событие, порядок регистрации имеет такое же значение.

События с аннотацией @Cancelable имеют особый эффект при отмене. Если событие отменено последующие слушатели с подобным событием не будут обрабатываться, пока не будет поставлена специальная аннотация:

Благодаря контролированию порядка, в котором вызываются слушатели, можно избежать возобновления события, отмененного в другом слушателе. Хотя и бывают особые обстоятельства, в которых приходится применять другие меры, дабы избежать логических ошибок.

Теперь вы можете поиграться со слушателями событий и переменными событий, чтобы понять что и когда вызывается, но добавлю предупреждающее словечко: многие события могут быть вызваны только на ОДНОЙ из сторон (клиент / сервер), так что если что-то работает не так, как задумано, проверьте на какой стороне может работать событие. Самый простой способ проверить вызывается ли метод, это поставить в начале каждого метода оповещатель в консоль об успешном выполнении:

Спойлер: Полное описание работы и применение самых полезных событий

ВАЖНО: Последующие события из 1.6.х; многие из них не изменились в новых версиях, но есть и поменявшиеся. Всегда заглядывайте в пакет net.minecraftforge.event для просмотра доступных событий, доступных в версии, на который вы пишите модификацию.

1. ArrowNockEvent
Параметры: EntityPlayer player, ItemStack result
Обычно вызывается из 'onItemRightClick'.
Применение: Т.к. событие отменяемое, вы можете при несоблюдении условий (например, нет стрел в инвентаре) прекратить прицеливание из лука.

2. ArrowLooseEvent
Параметры: EntityPlayer player, ItemStack bow, int charge
Обычно вызывается из 'onPlayerStoppedUsing'. Отменяем.
Применение: Применяется в тандеме описанном свыше, для проверки отсутствия стрел. Если стрел нет - событие отменяется.

3. EntityConstructing
Параметры: Entity entity
Вызывается с каждым объектом, если его конструктор вызван.
Применение: Полезен, если вам нужно добавить расширенные свойства (ExtendedEntityProperties).

4. EntityJoinWorldEvent
Параметры: Entity entity, World world
Вызывается когда любое существо попадает в мир первый раз.
Применение: Полезен для синхронизации расширенных свойств (ExtendedEntityProperties), также для выдачи предметов при первом входе игрока и т.п.

5. LivingUpdateEvent
Параметры: EntityLivingBase entity
Вызывается каждый тик в начале метода onUpdate() сущности.
Применение: Скорее всего, это самое полезное событие. Вы можете позволить игроку летать, если он держит определенный предмет
или одет в броню, вы можете изменить скорость падения игрока, вы можете добавить эффект зелья и многое другое, что сможете представить.
Это и вправду полезное событие.

6. LivingDropsEvent
Параметры: EntityLivingBase entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean
recentlyHit, int specialDropValue
Вызывается когда сущность умирает и выбрасывает предметы.
Применение: Удобен если вы хотите изменить дроп с ванильных мобов или добавить особый дроп, если вы убиваете предметом
из своего мода. Вы конечно можете удалить выпадающие предметы вообще. Полезно.

7. LivingFallEvent
Параметры: EntityLivingBase entity, float distance
Вызывается, когда сущность касается земли после падения.
ОБРАТИТЕ ВНИМАНИЕ: Это событие не вызывается в творческом режиме; PlayerFlyableFallEvent вместо него.
Применение: Отменяем, так что 'event.setCanceled(true)' отключается обработку падения.
Вы можете изменить высоту падения, но запомните, что событие срабатывает ТОЛЬКО при касании. Если хотите
изменить высоту падения в определенных условия, лучше применить LivingUpdateEvent.
Также, убедитесь что изменяете 'event.distance', а не 'entity.fallDistance', иначе вы не измените исход падения.

8. LivingJumpEvent
Параметры: EntityLivingBase entity
Вызывается всегда, когда сущность прыгает.
Применение: Полезно для 'entity.motionY += 10.0D'. Просто попробуйте.

9. LivingAttackEvent
Параметры: EntityLivingBase entity, DamageSource source, float ammount
Вызывается, когда сущность атакует.
Применение: Отменяемо. Здесь вы можете сделать предварительную обработку атаки перед событием LivingHurtEvent. Информация о
источнике атаки находится в DamageSource, так что вы можете изменить нужные вам параметры урона. Изменения
равнозначны таким же в событии LivingHurtEvent, но здесь сделаны они будут раньше.

10. LivingHurtEvent
Параметры: EntityLivingBase entity, DamageSource source, float ammount
Вызывается, когда сущность ранят.
Применение: Супер полезное событие, если вам нужно сделать броню которая будет оборонять от огненного урона, увеличивать
урон от магии и т.д.

11. LivingDeathEvent
Параметры: EntityLivingBase entity, DamageSource source
Вызывается, когда сущность умирает; отменяемо!
Применение: Напомню, что DamageSource имеет множество переменных, таких как getEntity(), которая возвращает существо
которое нанесло урон и исходя из этого - кто убийца. Можно отменить смерть и воскресить себя,
или установить таймер для воскрешения. Если у вас есть свойства которые должны добавляться при смерти игрока,
такие как IExtendedEntityProperties, вы можете добавить их здесь.

12. EntityInteractEvent
Параметры: EntityPlayer player, Entity target
Вызывается, когда игрок жмет ПКМ по существу.
Применение: Вы можете сделать много интересного с применением этого события. Одним из применений может оказаться сбор молока в ваше ведро.

13. EntityItemPickupEvent
Параметры: EntityPlayer player, EntityItem item
Вызывается, когда игрок поднимает предмет
Применение: Это полезное событие для тех предметов, которые должны как-то обрабатываться при подборе;
например, вы можете сделать что-то на подобие сфер опыта, сфер маны, которые восстанавливают ману, при подборе их с земли.

14. HarvestCheck
Параметры: EntityPlayer player, Block block, boolean success
Вызывается в момент, когда игрок сломал блок, но дроп еще не выпал
Применение: Может компоноваться с событием BreakSpeed, это, пожалуй, лучший способ изменить шахтерское ремесло.

[ASM] Создание своего отменяемого ивента

Всем привет. Нужна помощь по редактированию байт-кода через ASM. Вообщем, предположим есть класс майнкрафта с нужным мне методом. Мне нужно "пропатчить" этот метод. Как зарегать ASM plugin, перегнать byte[] в ClassNode и вернуть обратно в byte[] - знаю, особо объяснений не требуется. Как вставить, например вызова метода в инструкции метода - тоже знаю и уже делал.

Но в этот раз мне нужно кое-что сложнее - отменяемое событие. Конкретно в случае, из-за которого пишу сейчас - мне достаточно будет вызвать кастом событие в самом начале реализации метода и просто return`уть, если ивент отменён. Как и всегда, я использую в помощь ASM ByteCode Viewer плагин IDEA, и именно тут загвостка: как я понял, ветки if-else; try-catch; циклы и подобные конструкции используют Labels (метки), которые показываются плагинов в виде L0, L1, Ln. Я попробовал скомпилить класс, где есть простенький if - и как раз, в ASM Viewer появились те самые L0 L1 и IFEQ(который, как я понимаю, отвечает за то, какую ветку нужно выбрать в зависимости от результата проверки if).

Для реализации того, что мне нужно (вставить свой отменяемый ивент в метод из майнкрафта), мне кажется нужно создать InsnList(), вставить в начало этого листа создание и пост ивента в MinecraftForge.EVENT_BUS, а затем как-то (КАК. ) создать L1, где будет InsnNode(Opcodes.RETURN) и L2, куда я скопирую все инструкции метода (то есть ивент не отменился - делаем то, что в этом методе есть), затем очистить инструкции в методе через method.instructions.clear() и вставить те инструкции, которые у меня получились в InsnList(). Но вот, увы, весь вечер просидел в гугле и не смог найти, как вставить if() < >else <> с помощью ASM в код. Помогите, пожалуйста!

GlassSpirit
А, вижу, что там как раз нет отменяемых событий, ладно.
Вот рандомный кусок кода, который я нарыл на просторах интернета. Он вроде показывает как вставить if-else с return.
will0376
Похвально, что ты пошел в асм, но не проще ли будет использовать миксин?
GlassSpirit

Эти ресурсы уже смотрел? Во втором вроде есть как раз то, что тебе нужно.

[Гайды][1.9.2] Создание плагина spigot, часть 2 - "Эвенты"

[Гайды][1.9.2] Создание плагина spigot, часть 2 - "Эвенты"

import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin implements Listener < // Теперь мы следим за событиями

public void onEnable() Bukkit.getServer().getPluginManager().registerEvents(this, this); // регестрируем эвенты в этом классе
getLogger().info("Hello. ");
>

public void onDisable() getLogger().info("Bye. ");
>

[Гайды][1.9.2] Создание плагина spigot, часть 2 - "Эвенты"

Теперь экспортируем плагин(читаем об этом в предыдущем гайде),
и теперь мы при заходе на сервер видим:

[Гайд] Все о сервере майнкрафт

[Гайд] Все о сервере майнкрафт


Не буду болтать и давайте же приступим.Каждый день, я буду добавлять по одно главе, начнем с основы основ Т_Т
1.Основа
Прежде чем создать сервер, вы должны понять две вещи: 1. За сервер придется платить 2. Сервер может не окупаться

Моды: Моды. моды.. Ставьте только небольшое кол-во модов, ибо много модов слишком плохо.. Так же как и с плагинами, нужно выбрать подходящие моды под ваши тематики, иначе будет не очень круто бегать с деревянным мечом в то время, как дома ты качаешь нефть и проводишь электричество.

Лаунчер:Лаунчер - довольно полезная вещь для любого сервера, в нем есть как и плюсы, так и минусы.
Начну с минусов: Лаунчер - програмка.exe школьники частенько боятся её открывать. Ну а другим, иногда лень качать
Лаунчеры без сомнения нужны только популярным серверам
Плюсы: Защита от читов, моды, и просто полезная программка:)

Читайте также: