- Версия(и) Minecraft
- 1.12+
Доброго времени суток, господа.
Этот туториал ориентирован, прежде всего, на новичков и ничего сложного не представляет. Здесь я даже не упомяну про рендер, пользуясь исключительно ванильными средствами.
Однако, на эту версию подобных статей практически нет, и я думаю лишней она не будет.
Ну а те, кто не новички, возможно, найдут что-нибудь интересное в главе 5.
Ладно, хватит лирики, поехали!
Этот туториал ориентирован, прежде всего, на новичков и ничего сложного не представляет. Здесь я даже не упомяну про рендер, пользуясь исключительно ванильными средствами.
Однако, на эту версию подобных статей практически нет, и я думаю лишней она не будет.
Ну а те, кто не новички, возможно, найдут что-нибудь интересное в главе 5.
Ладно, хватит лирики, поехали!
Содержание:
- Глава 0. Предисловие
- Глава 1. Подготовка
- Глава 2. Класс entity
- Глава 3. Рендер
- Глава 4. Привязка entity к предмету
- Глава 5. Для продвинутых
Глава 0. Предисловие:
Мы создадим летающее яблоко. Да, как бы странно это не звучало. Более того, это яблоко будет наносить довольно большой урон по слизням.
Глава 1. Подготовка:
1.Будет неплохо, если у нас уже есть готовый предмет, или на худой конец основа мода и настроенный прокси. Если вы этого не сделали, советую заглянуть сюда: Прокси, Предмет.
2.Также нам потребуется сделать инстанцию.
Для этого в главном классе нашего мода (в моём случае он называется FlyApple) добавим вот такой код:
Java:
//Инстанция нашего мода. Потребуется для создания нашего entity
@Instance(Info.ID) // В данном случае Info.ID - это id мода
public static FlyApple instance;
Глава 2. Класс entity:
В основном пакете мода (в моём случае это ru.mousecray.flyapple) создадим пакет entity.
Далее создадим класс EntityFlyApple:
Java:
//Вообще-то мы могли бы наследовать от EntitySnowball, однако
//в нашем случае, это ничего не даст + придётся
//переопределить лишний метод, и оставить его пустым.
public class EntityFlyApple extends EntityThrowable {
//Три блока ниже - это конструкторы. На разные случаи жизни.
public EntityFlyApple(World world) {
super(world);
}
public EntityFlyApple(World world, EntityLivingBase thrower) {
super(world, thrower);
}
public EntityFlyApple(World world, double x, double y, double z) {
super(world, x, y, z);
}
//Вызов различных событий (частицы, звуки), при попадени снаряда в цель (живое существо, блок)
@Override
@SideOnly(Side.CLIENT)
public void handleStatusUpdate(byte id) {
if (id == 3) {
for (int i = 0; i < 8; ++i) {
//Появляются частицы лавы. В обычном майнкрафте они образуются на потолке, если сверху лава.
this.world.spawnParticle(EnumParticleTypes.DRIP_LAVA, this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
}
}
}
//Вызывается, когда предмет попадает в цель (живое существо, блок)
@Override
protected void onImpact(RayTraceResult result) {
//Проверяем, что цель - это другой entity
if (result.entityHit != null) {
//Урон от яблока по умолчанию
int i = 0;
//Урон от яблока, если цель - это слизень
if (result.entityHit instanceof EntitySlime) {
i = 3;
}
//Атакуем цель, в качестве 1-ого аргумента, передаём хозяина снаряда,
//а в качестве 2-ого - урон.
//Хозяин снаряда нужен, чтобы при смерти цели, можно было вывести сообщение о виновнике смерти.
//Не писать же, что убийца - стрела или яблоко)
//DamageSource.causeThrownDamage относится к так называемому косвенному урону, то-есть урону,
//с помощью подручных средств, в нашем случае с помощью яблока.
result.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), (float)i);
}
//Проверяем, что мир - "ВсёКромеКлиента", то-есть мир НЕ подключён к какому-либо серверу,
//а значит сам является сервером. Имеется в виду ЛОГИЧЕСКИЙ сервер
if (!this.world.isRemote) {
//Название метода не очень корректное. Отправляет пакет с "действием" нашего снаряда,
//где идентификтором выступает байт
this.world.setEntityState(this, (byte)3);
//entity умирает
this.setDead();
}
}
}
добавим вот эту строчку:
Java:
EntityRegistry.registerModEntity(new ResourceLocation("flyapple", "flying_apple"), EntityFlyApple.class, "flyapple:flying_apple", 0, FlyApple.instance, 64, 20, true);
EntityFlyApple.class - Имя класса нашего entity.
"flyapple:flying_apple" - Имя entity. Рекомендуется писать в стиле modid:name чтобы не было конфликтов с майнкрафтом.
0 - Идентификатор нашего entity. В одном моде, у каждого entity должен быть свой уникальный id.
FlyApple.instance - То, о чём мы говорили в первой главе - инстанция.
64, 20 - 1. Радиус, в котором entity будет замечать других существ; 2.Частота этого наблюдения.
true - Нужно ли слать пакеты об изменении скорости. Не имеет смысла, для неподвижных существ.
Теперь мы можем запустить игру и посмотреть, что получилось.
Мы можем призвать наш entity, однако не увидим его. Ведь мы не сделали ему рендер.
Глава 3. Рендер:
В отличии от других примеров по созданию entity мы Не будем делать свой рендер, мы просто используем ванильный класс RenderSnowball.
Итак, приступим!
После 1.12 случилось? обновление, и стандартный метод регистрации стал @Deprecated. В связи с этим нам нужно создавать класс-наследник IRenderFactory. Суть в том, что для каждого "снаряда", придётся создавать новый класс IRenderFactory, пусть даже анонимный. Это не очень удобно, поэтому мы создадим один общий класс для всех EntityTrowable. Начнём.
В главном пакете мода создадим пакет render, а в нём класс SnowballRenderFactory:
Java:
public class SnowballRenderFactory implements IRenderFactory {
public final Item item;
//Конструктор. В него мы передаём предмет, от которого нужно взять текстуру
public SnowballRenderFactory(Item item) {
this.item = item;
}
@Override
public Render createRenderFor(RenderManager manager) {
//Возвращаем рендер снежка, и передаём предмет, который мы инициализировали в конструкторе
return new RenderSnowball(manager, item, Minecraft.getMinecraft().getRenderItem());
}
}
Java:
//Регистрируем рендер, и в качестве 1-ого аргумента передаём класс нашего entity,
//а в качестве второго - наш RenderFactory. Items.APPLE - предмет, с которого entity
//возьмёт текстуру.
RenderingRegistry.registerEntityRenderingHandler(EntityFlyApple.class, new SnowballRenderFactory(Items.APPLE));
После того, как мы всё сделали, запустим игру и посмотрим, что получилось:
Чтобы призвать entity, введите вот такую команду:
/summon flyapple:flying_apple ~2 ~2 ~ {Motion:[1.0,0.0,0.0]}
Глава 4. Привязка entity к предмету:
Мы ведь хотим, чтобы у нас не просто был свой снаряд, но и чтобы его можно было кинуть с помощью предмета. Всё, что нам нужно, это добавить в класс предмета вот этот метод:
Java:
//Метод вызывается, когда игрок кликет ПКМ с предметом
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
//Получаем стак в руке игрока
ItemStack itemstack = player.getHeldItem(hand);
//Проверяем, что игрок НЕ в творческом режиме
if (!player.capabilities.isCreativeMode) {
//Уменьшаем стак на 1
itemstack.shrink(1);
}
//Проигрываем звук
world.playSound((EntityPlayer)null, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (itemRand.nextFloat() * 0.4F + 0.8F));
//Делаем задержку между бросаниями
player.getCooldownTracker().setCooldown(this, 20);
if (!world.isRemote) {
//Создаём объект нашего летающего яблока
EntityFlyApple apple = new EntityFlyApple(world, player);
//Поворачиваем его "лицом" к игроку и устанавливаем параметры движения
apple.setHeadingFromThrower(player, player.rotationPitch, player.rotationYaw, 0.0F, 1.5F, 1.0F);
//Призываем наш entity
world.spawnEntity(apple);
}
//Для статистики
player.addStat(StatList.getObjectUseStats(this));
//Возвращаем успешное действие, то-есть при ПКМ рука дёрнется как будто игрок кинул предмет
return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, itemstack);
}
Глава 5. Для продвинутых:
Итак, мы дошли до цели. Но, предположим, что ты, читатель, не совсем новичок! Тогда тебе может показаться мало того, что я написал. И именно на этот случай я подготовил эту главу. Она будет короткой, но в ней ты найдёшь информацию, для ещё большей кастомизации нашего с тобой предмета.
Нет, не нашего с тобой предмета, ТВОЕГО!
- Допустим, ты хочешь, чтобы твой entity появлялся, при использовании ванильного предмета. Без проблем. Однако, тебе потребуется сделать свой EventHandler. Самый обычный - EVENT_BUS. Дальше тебе нужно добавить эвент, который будет ниже. Код практически идентичен коду, который я использовал в 4-ой главе, поэтому без комментариев:
Java:
@SubscribeEvent public static void onItemRightClick(PlayerInteractEvent.RightClickItem event) { ItemStack stack = event.getItemStack(); if(stack.getItem() == Items.APPLE) { EntityPlayer player = event.getEntityPlayer(); World world = event.getWorld(); if (!player.capabilities.isCreativeMode) { stack.shrink(1); } world.playSound((EntityPlayer)null, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (new Random().nextFloat() * 0.4F + 0.8F)); player.getCooldownTracker().setCooldown(stack.getItem(), 20); if (!world.isRemote) { EntityFlyApple apple = new EntityFlyApple(world, player); apple.setHeadingFromThrower(player, player.rotationPitch, player.rotationYaw, 0.0F, 1.5F, 1.0F); world.spawnEntity(apple); } } }
- Помнишь метод setHeadingFromThrower? Да, да в 4-ой главе. К слову сказать, в конструкторе entity можно использовать метод похожий на вышеупомянутый, за исключением, пожалуй, параметров скорости, и зависимости от игрока: setThrowableHeading.
Параметры метода:
x, y, z - Буквально, движение. Задаёт направление перемещения;
Velocity - скорость полёта пули;
Accuracy - разброс при стрельбе.
- Ты всё ещё можешь регистрировать рендер entity без использования IRenderFactory, но этот метод регистрации помечен аннотацией @Deprecated. Используй его, на свой страх и риск
- В пакете net.minecraft.entity.projectile ты сможешь найти ванильные классы всех "летучих" entity, но такие entity как фейерверк, жемчужина эндера и глаз эндера, находятся в пакете net.minecraft.entity.item.
- Все рендеры ванильных entity можно найти в пакете net.minecraft.client.renderer.entity.
[1.8] EntityBullet - Классическая пуля
Entities - Minecraft Modding Tutorial 1.12/1.13 - Episode 10
[1.12.2]Rendering EntityThrowable with RenderSnowball
[1.12.2]Render Tutorial
[1.12] Registering entities
Introduce entity entry builder, useful in the Register e…
[1.11] How do you render a throwable entity?
[SOLVED] [1.12.2] Create Custom Projectile (similar to arrow
Github-|
|-WIPTech/src/main/java/cadiboo/wiptech/entity/projectile/EntityParamagneticProjectile113.java
|-WIPTech/src/main/java/cadiboo/wiptech/init/Entities.java
|-WIPTech/src/main/java/cadiboo/wiptech/handler/EventSubscriber.java
|-WIPTech/src/main/java/cadiboo/wiptech/client/EventSubscriber.java
[Forge] 1.7.X- Custom Item with Throwable Entity
[SOLVED][1.12] Throwable Entity not rendering
Entities - Minecraft Modding Tutorial 1.12/1.13 - Episode 10
[1.12.2]Rendering EntityThrowable with RenderSnowball
[1.12.2]Render Tutorial
[1.12] Registering entities
Introduce entity entry builder, useful in the Register e…
[1.11] How do you render a throwable entity?
[SOLVED] [1.12.2] Create Custom Projectile (similar to arrow
Github-|
|-WIPTech/src/main/java/cadiboo/wiptech/entity/projectile/EntityParamagneticProjectile113.java
|-WIPTech/src/main/java/cadiboo/wiptech/init/Entities.java
|-WIPTech/src/main/java/cadiboo/wiptech/handler/EventSubscriber.java
|-WIPTech/src/main/java/cadiboo/wiptech/client/EventSubscriber.java
[Forge] 1.7.X- Custom Item with Throwable Entity
[SOLVED][1.12] Throwable Entity not rendering