- Версия(и) Minecraft
- 1.12+
Здравствуйте. В этой статье речь пойдёт о мылозельеварении и всем что с этим связано. Будут рассмотрены процессы создания эффектов, добавления зелий как предметов и рецептов для них, а так же некоторые связанные с этим хитрости. Исходники доступны в моём репозитории.
Создание эффекта
Эффекты бывают разные и их реализация зависит от конкретной задачи. Большую часть действий можно (и нужно) производить в самом классе эффекта, однако есть и исключения. В этом разделе будут рассмотрены следующие разновидности эффектов:
Примеры: зелье лечения, мгновенный урон.
Чтобы создать такой эффект необходимо в его классе переопределить
Периодический эффект
Примеры: регенерация, отравление.
Для такого эффекта требуется переопределение
Метод
Эффект с модификацией атрибутов
Примеры: скорость, спешка, повышение урона.
Эффект позволяет произвести какое либо действие однократно при применении и истечении времени действия эффекта. Ванильные эффекты используют эту возможность для изменения атрибутов, а мы можем приспособить их для чего нибудь ещё.
при удалении.
Эффект с действием вне класса
Примеры: невидимость.
Бывают случаи когда применить эффект в его классе не получается.
Для этого для отслеживания активности эффекта в классе EntityLivingBase содержится несколько методов:
Ну а теперь перейдём к практике. В качестве примера я опишу процесс создания эффекта с периодическим действием, который будет лечить игрока в обмен на очки опыта (два уровня - лечение раз в секунду или раз пол секунды). Примеры остальных эффектов смотрите на GitHub.
В первую очередь для эффекта требуется создать класс-наследник Potion, я назвал его PotionEquilibrium:
Суперконструктор требует логическую переменную, определяющую вредный это эффект или нет и целочисленное значение, отвечающее за цвет колбы зелья и частиц, окружающих игрока если эффект активен. В конструктор я добавил строку, определяющую имя эффекта. Требуется задать обычное имя и регистрационное.
Локализация названия эффекта. Имя будет задано при инициализации эффекта чуть позже.
Переопределение
Эффекту необходима иконка. Что бы её добавить создаем константу для пути к иконке, инициализируем в конструкторе, переопределяем и наполняем методы рендера. В данном случае название иконки совпадает с названием эффекта:
Разместите иконку в папке "src\main\resources\assets\ваш modid\textures\potions":
В итоге класс должен выглядеть как то так:
Регистрация... Теперь никакой рефлексии для расширения массивов, всё как у людей, спасибо команде Forge. Для объявления и регистрации эффектов создадим отдельный класс PotionsRegistry. Так как регистрация эффектов происходит через эвент RegistryEvent.Register, пометим класс аннотацией
Фордж подгрузит класс и метод с регистрацией самостоятельно.
Ну вот и всё. Используя
можно добавить игроку этот эффект, предварительно обернув его в PotionEffect. Стандартные эффекты перенесены из Potion в MobEffects.
В игре на данный момент присутствуют три разновидности зелий, однако все они управляются одним объектом PotionType. Он представляет собой набор эффектов, которые содержит зелье. Все виды зелий создаются автоматически "за кулисами" при регистрации этого объекта. Время действия обычных и взрывных зелий приравнивается ко времени действия эффекта, а оседающие зелья получают четырёхкратно уменьшенную продолжительность. Они автоматически будут добавлены во вкладку с зельями и получат стандартное форматирование тултипов.
Таким образом всё что нужно сделать для создания зелий это создать новый PotionType и зарегистрировать его. Создадим зелья с нашим эффектом, которые будут иметь каноничные модификации в виде увеличенного времени действия и силы. Делать всё это будем в нашем PotionsRegistry:
Стоит отметить, что если использовать расширенный конструктор PotionEffect и отключить рендер частиц зелья вокруг ентити (
Локализация зелий:
Регистрация аналогична эффектам, происходит автоматом.
Осталось добавить рецепты зельям. Есть два способа:
Для добавления рецептов аналогичных стандартным рекомендую использовать
Второй способ это использование
Для зелья из примера создадим рецепт первым способом. В классе PotionsRegistry:
Зелье можно будет сварить из основы в виде неловкого зелья и склянки с опытом, продлить редстоуном или усилить светопылью - как в ванили. Регистрируются рецепты в CommonProxy в процессе инициализации.
Дополнительно: зелья в качестве компонента при крафте
Вы можете добавить для варочной стойки рецепт, ингредиентом в котором будет зелье. В исходниках есть рабочий пример, но тут приведу метод регистрации такого рецепта и класс рецепта:
Для зелий других типов используйте
Если хотите использовать зелье в крафтах на верстаке, то рецепт может выглядеть примерно так (рабочий в исходниках):
Поместив простое зелье из статьи в центр сетки крафта вы получите склянку с опытом.
Всё, на этом туториал завершён. Оставляйте свои комментарии и советы в обсуждении. Спасибо за внимание.
Зельеварение
В последних версиях работа с зельями стала проще, и здесь я опишу полный алгоритм создания собственных крафтовых зелий.
Создание эффекта
Эффекты бывают разные и их реализация зависит от конкретной задачи. Большую часть действий можно (и нужно) производить в самом классе эффекта, однако есть и исключения. В этом разделе будут рассмотрены следующие разновидности эффектов:
- эффекты с моментальным действием;
- эффекты с периодическим действием;
- эффекты временно модифицирующие атрибуты;
- эффекты с реализацией вне своего класса.
Примеры: зелье лечения, мгновенный урон.
Чтобы создать такой эффект необходимо в его классе переопределить
Potion#isInstant()
и вернуть в нём true
и Potion#affectEntity()
. Метод affectEntity()
будет вызван единожды при применении эффекта.
Java:
@Override
public boolean isInstant() {
return true;
}
@Override
public void affectEntity(@Nullable Entity source, @Nullable Entity indirectSource, EntityLivingBase entityLivingBase, int amplifier, double health) {
//Применение
}
Периодический эффект
Примеры: регенерация, отравление.
Для такого эффекта требуется переопределение
Potion#isReady()
и Potion#performEffect()
.Метод
performEffect()
буден вызван только если isReady()
вернёт true
. Так как вызов isReady()
происходит каждый игровой тик можно организовать применение эффекта с необходимой частотой используя нехитрую логическую конструкцию с делением по модулю.
Java:
@Override
public void performEffect(EntityLivingBase entityLivingBase, int amplifier) {
//Применение
}
@Override
public boolean isReady(int duration, int amplifier) {
return duration % 20 == 0;//true каждую секунду.
}
Эффект с модификацией атрибутов
Примеры: скорость, спешка, повышение урона.
Эффект позволяет произвести какое либо действие однократно при применении и истечении времени действия эффекта. Ванильные эффекты используют эту возможность для изменения атрибутов, а мы можем приспособить их для чего нибудь ещё.
Potion#applyAttributesModifiersToEntity()
вызывается при применении, а Potion#removeAttributesModifiersFromEntity()
при удалении.
Java:
@Override
public void applyAttributesModifiersToEntity(EntityLivingBase entityLivingBase, AbstractAttributeMap attributeMap, int amplifier) {
//Добавление
}
@Override
public void removeAttributesModifiersFromEntity(EntityLivingBase entityLivingBase, AbstractAttributeMap attributeMap, int amplifier) {
//Удаление
}
Эффект с действием вне класса
Примеры: невидимость.
Бывают случаи когда применить эффект в его классе не получается.
Для этого для отслеживания активности эффекта в классе EntityLivingBase содержится несколько методов:
EntityLivingBase#isPotionActive(Potion)
- проверка наличия эффекта,EntityLivingBase#getActivePotionEffect(Potion)
- получение эффекта (можно получить описание с помощью геттеров).Ну а теперь перейдём к практике. В качестве примера я опишу процесс создания эффекта с периодическим действием, который будет лечить игрока в обмен на очки опыта (два уровня - лечение раз в секунду или раз пол секунды). Примеры остальных эффектов смотрите на GitHub.
В первую очередь для эффекта требуется создать класс-наследник Potion, я назвал его PotionEquilibrium:
Java:
public class PotionEquilibrium extends Potion {
public PotionEquilibrium(String potionName, boolean isBadEffect, int liquidColor) {
super(isBadEffect, liquidColor);
this.setName(potionName);
}
public void setName(String potionName) {
this.setRegistryName(PotionsMain.MODID, potionName);//Ваш modid первым параметром.
this.setPotionName("effect." + this.getRegistryName().toString());
}
}
Суперконструктор требует логическую переменную, определяющую вредный это эффект или нет и целочисленное значение, отвечающее за цвет колбы зелья и частиц, окружающих игрока если эффект активен. В конструктор я добавил строку, определяющую имя эффекта. Требуется задать обычное имя и регистрационное.
Локализация названия эффекта. Имя будет задано при инициализации эффекта чуть позже.
effect.potions:equilibrium=Равноценный обмен
Переопределение
isReady()
и performEffect()
, реализация эффекта. Как сразу становится видно наш эффект будет иметь два уровня (применение каждую секунду и применение раз в секунду):
Java:
@Override
public void performEffect(EntityLivingBase entityLivingBase, int amplifier) {
if (entityLivingBase instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entityLivingBase;
if (player.getHealth() < player.getMaxHealth()) {
if (player.experienceLevel >= 1) {
player.heal(2.0F);//Хил 2 пункта (1 сердце).
player.experienceLevel -= 1;//За один уровень опыта.
}
}
}
}
@Override
public boolean isReady(int duration, int amplifier) {
return duration % (amplifier == 0 ? 20 : 10) == 0;
}
Эффекту необходима иконка. Что бы её добавить создаем константу для пути к иконке, инициализируем в конструкторе, переопределяем и наполняем методы рендера. В данном случае название иконки совпадает с названием эффекта:
Java:
public class PotionEquilibrium extends Potion {
private final ResourceLocation icon;
public PotionEquilibrium(String potionName, boolean isBadEffect, int liquidColor) {
super(isBadEffect, liquidColor);
this.icon = new ResourceLocation(PotionsMain.MODID, "textures/potions/" + potionName + ".png");
}
@Override
public boolean hasStatusIcon() {
return false;
}
@SideOnly(Side.CLIENT)
@Override
public void renderInventoryEffect(int x, int y, PotionEffect potionEffect, Minecraft mc) {
if (mc.currentScreen != null) {
mc.getTextureManager().bindTexture(this.icon);
Gui.drawModalRectWithCustomSizedTexture(x + 6, y + 7, 0, 0, 18, 18, 18, 18);
}
}
@SideOnly(Side.CLIENT)
@Override
public void renderHUDEffect(int x, int y, PotionEffect potionEffect, Minecraft mc, float alpha) {
mc.getTextureManager().bindTexture(this.icon);
Gui.drawModalRectWithCustomSizedTexture(x + 3, y + 3, 0, 0, 18, 18, 18, 18);
}
}
Разместите иконку в папке "src\main\resources\assets\ваш modid\textures\potions":
В итоге класс должен выглядеть как то так:
Java:
public class PotionEquilibrium extends Potion {
private final ResourceLocation icon;
public PotionEquilibrium(String potionName, boolean isBadEffect, int liquidColor) {
super(isBadEffect, liquidColor);
this.setName(potionName);
this.icon = new ResourceLocation(PotionsMain.MODID, "textures/potions/" + potionName + ".png");
}
public void setName(String potionName) {
this.setRegistryName(PotionsMain.MODID, potionName);
this.setPotionName("effect." + this.getRegistryName().toString());
}
@Override
public void performEffect(EntityLivingBase entityLivingBase, int amplifier) {
if (entityLivingBase instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entityLivingBase;
if (player.getHealth() < player.getMaxHealth()) {
if (player.experienceLevel >= 1) {
player.heal(2.0F);//Хил 2 пункта (1 сердце).
player.experienceLevel -= 1;//За один уровень опыта.
}
}
}
}
@Override
public boolean isReady(int duration, int amplifier) {
return duration % (amplifier == 0 ? 20 : 10) == 0;
}
@Override
public boolean hasStatusIcon() {
return false;
}
@SideOnly(Side.CLIENT)
@Override
public void renderInventoryEffect(int x, int y, PotionEffect potionEffect, Minecraft mc) {
if (mc.currentScreen != null) {
mc.getTextureManager().bindTexture(this.icon);
Gui.drawModalRectWithCustomSizedTexture(x + 6, y + 7, 0, 0, 18, 18, 18, 18);
}
}
@SideOnly(Side.CLIENT)
@Override
public void renderHUDEffect(int x, int y, PotionEffect potionEffect, Minecraft mc, float alpha) {
mc.getTextureManager().bindTexture(this.icon);
Gui.drawModalRectWithCustomSizedTexture(x + 3, y + 3, 0, 0, 18, 18, 18, 18);
}
}
Регистрация... Теперь никакой рефлексии для расширения массивов, всё как у людей, спасибо команде Forge. Для объявления и регистрации эффектов создадим отдельный класс PotionsRegistry. Так как регистрация эффектов происходит через эвент RegistryEvent.Register, пометим класс аннотацией
@Mod.EventBusSubscriber(modid = Main.MODID)
, которая обеспечит автоматическое подключение методов-эвентов (с аннотацией @SubscribeEvent
) при загрузке мода:
Java:
@Mod.EventBusSubscriber(modid = PotionsMain.MODID)
public class PotionsRegistry {
/** Эффекты */
public static final Potion
EQUILIBRIUM = new PotionEquilibrium("equilibrium", false, 0x77FFA9);//Периодический эффект (обмен опыта на здоровье).
@SubscribeEvent
public static void registerPotions(RegistryEvent.Register<Potion> event) {
event.getRegistry().registerAll(
EQUILIBRIUM
);
}
}
Фордж подгрузит класс и метод с регистрацией самостоятельно.
Ну вот и всё. Используя
EntityLivingBase#addPotionEffect()
,можно добавить игроку этот эффект, предварительно обернув его в PotionEffect. Стандартные эффекты перенесены из Potion в MobEffects.
Создание зелья
В игре на данный момент присутствуют три разновидности зелий, однако все они управляются одним объектом PotionType. Он представляет собой набор эффектов, которые содержит зелье. Все виды зелий создаются автоматически "за кулисами" при регистрации этого объекта. Время действия обычных и взрывных зелий приравнивается ко времени действия эффекта, а оседающие зелья получают четырёхкратно уменьшенную продолжительность. Они автоматически будут добавлены во вкладку с зельями и получат стандартное форматирование тултипов.
Таким образом всё что нужно сделать для создания зелий это создать новый PotionType и зарегистрировать его. Создадим зелья с нашим эффектом, которые будут иметь каноничные модификации в виде увеличенного времени действия и силы. Делать всё это будем в нашем PotionsRegistry:
Java:
@Mod.EventBusSubscriber(modid = PotionsMain.MODID)
public class PotionsRegistry {
/** Эффекты */
public static final Potion
EQUILIBRIUM = new PotionEquilibrium("equilibrium", false, 0x77FFA9);//Периодический эффект (обмен опыта на здоровье).
/** "Типы", представляющие зелья как предметы */
public static final PotionType
EQUILIBRIUM_TYPE_STANDARD = createPotionType(null, new PotionEffect(EQUILIBRIUM, 600)),
EQUILIBRIUM_TYPE_LONG = createPotionType("long", new PotionEffect(EQUILIBRIUM, 900)),
EQUILIBRIUM_TYPE_STRONG = createPotionType("strong", new PotionEffect(EQUILIBRIUM, 600, 1));
/**
* Возвращает новый экземпляр PotionType с именем эффекта.
*
* @param namePrefix
* @param potionEffect
*
* @return PotionType
*/
private static PotionType createPotionType(String namePrefix, PotionEffect potionEffect) {
ResourceLocation potionName = potionEffect.getPotion().getRegistryName();
ResourceLocation potionTypeName;
if (namePrefix != null)
potionTypeName = new ResourceLocation(potionName.getResourceDomain(), namePrefix + "_" + potionName.getResourcePath());
else
potionTypeName = potionName;
return new PotionType(potionName.toString(), potionEffect).setRegistryName(potionTypeName);
}
/**
* Возвращает новый экземпляр PotionType с указанным именем. Используется для зелий с несколькими эффектами.
*
* @param typeName
* @param namePrefix
* @param potionEffects
*
* @return PotionType
*/
private static PotionType createCompositePotionType(String typeName, String namePrefix, PotionEffect... potionEffects) {
ResourceLocation potionTypeName;
if (namePrefix != null)
potionTypeName = new ResourceLocation(PotionsMain.MODID, namePrefix + "_" + typeName);
else
potionTypeName = new ResourceLocation(PotionsMain.MODID, typeName);
return new PotionType(typeName, potionEffects).setRegistryName(potionTypeName);
}
@SubscribeEvent
public static void registerPotions(RegistryEvent.Register<Potion> event) {
event.getRegistry().registerAll(
EQUILIBRIUM
);
}
@SubscribeEvent
public static void registerPotionTypes(RegistryEvent.Register<PotionType> event) {
event.getRegistry().registerAll(
EQUILIBRIUM_TYPE_STANDARD,
EQUILIBRIUM_TYPE_LONG,
EQUILIBRIUM_TYPE_STRONG
);
}
}
Стоит отметить, что если использовать расширенный конструктор PotionEffect и отключить рендер частиц зелья вокруг ентити (
false
последним параметром) при создании PotionType, то цвет колбы такого зелья будет чёрным.Локализация зелий:
Код:
potion.effect.potions:equilibrium=Зелье Равноценного обмена
splash_potion.effect.potions:equilibrium=Взрывное Зелье Равноценного обмена
lingering_potion.effect.potions:equilibrium=Оседающее Зелье Равноценного обмена
Регистрация аналогична эффектам, происходит автоматом.
Рецепты
Осталось добавить рецепты зельям. Есть два способа:
Для добавления рецептов аналогичных стандартным рекомендую использовать
PotionHelper#addMix(PotionType, Item, PotionType)
, где параметры: основа, ингредиент, результат соответственно. В качестве основы можно задать как стандартные основы (PotionTypes#AWKWARD
, PotionTypes#MUNDANE
и PotionTypes#THICK
) так и любые другие зелья. Результат так же может быть любым зельем. Минус этого способа состоит в типе ингредиента, который должен быть инстансом Item, что не позволит использовать в качестве ингредиентов другие зелья и проверять NBT. Все ванильные зелья зарегистрированы таким образом.Второй способ это использование
BrewingRecipeRegistry#addRecipe(ItemStack, ItemStack, ItemStack)
. Однако этот метод не сверяет NBT переданных стаков и поэтому адекватной работы от него не ждите. Для добавления собственных рецептов с зельями в качестве ингредиентов в частности единственным решением является создание собственного рецепта с реализацией IBrewingRecipe и использование перегруженного BrewingRecipeRegistry#addRecipe(IBrewingRecipe)
для его регистрации. Пример вы можете найти в исходниках в моём репозитории.Для зелья из примера создадим рецепт первым способом. В классе PotionsRegistry:
Java:
public static void registerSimpleRecipes() {
addStandardRecipes(EQUILIBRIUM_TYPE_STANDARD, EQUILIBRIUM_TYPE_LONG, EQUILIBRIUM_TYPE_STRONG, Items.EXPERIENCE_BOTTLE);
}
/**
* Создание стандартных рецептов для зелий.
*
* @param standardPotionType
* @param longPotionType
* @param strongPotionType
* @param ingredient
*/
private static void addStandardRecipes(PotionType standardPotionType, PotionType longPotionType, PotionType strongPotionType, Item ingredient) {
PotionHelper.addMix(PotionTypes.AWKWARD, ingredient, standardPotionType);//Аргументы: основа, ингредиент, результат.
if (longPotionType != null)
PotionHelper.addMix(standardPotionType, Items.REDSTONE, longPotionType);
if (strongPotionType != null)
PotionHelper.addMix(standardPotionType, Items.GLOWSTONE_DUST, strongPotionType);
}
/**
* Добавление своего рецепта.
*
* @param basePotionType
* @param ingredient
* @param outputPotiontype
*/
private static void addRecipe(PotionType inputPotionType, Item ingredient, PotionType outputPotiontype) {
PotionHelper.addMix(inputPotionType, ingredient, outputPotiontype);
}
Java:
@Mod.EventBusSubscriber(modid = PotionsMain.MODID)
public class PotionsRegistry {
/** Эффекты */
public static final Potion
EQUILIBRIUM = new PotionEquilibrium("equilibrium", false, 0x77FFA9);//Периодический эффект (обмен опыта на здоровье).
/** "Типы", представляющие зелья как предметы */
public static final PotionType
EQUILIBRIUM_TYPE_STANDARD = createPotionType(null, new PotionEffect(EQUILIBRIUM, 600)),
EQUILIBRIUM_TYPE_LONG = createPotionType("long", new PotionEffect(EQUILIBRIUM, 900)),
EQUILIBRIUM_TYPE_STRONG = createPotionType("strong", new PotionEffect(EQUILIBRIUM, 600, 1));
public static void registerSimpleRecipes() {
addStandardRecipes(EQUILIBRIUM_TYPE_STANDARD, EQUILIBRIUM_TYPE_LONG, EQUILIBRIUM_TYPE_STRONG, Items.EXPERIENCE_BOTTLE);
}
/**
* Возвращает новый экземпляр PotionType с именем эффекта.
*
* @param namePrefix
* @param potionEffect
*
* @return PotionType
*/
private static PotionType createPotionType(String namePrefix, PotionEffect potionEffect) {
ResourceLocation potionName = potionEffect.getPotion().getRegistryName();
ResourceLocation potionTypeName;
if (namePrefix != null)
potionTypeName = new ResourceLocation(potionName.getResourceDomain(), namePrefix + "_" + potionName.getResourcePath());
else
potionTypeName = potionName;
return new PotionType(potionName.toString(), potionEffect).setRegistryName(potionTypeName);
}
/**
* Возвращает новый экземпляр PotionType с указанным именем. Используется для зелий с несколькими эффектами.
*
* @param typeName
* @param namePrefix
* @param potionEffects
*
* @return PotionType
*/
private static PotionType createCompositePotionType(String typeName, String namePrefix, PotionEffect... potionEffects) {
ResourceLocation potionTypeName;
if (namePrefix != null)
potionTypeName = new ResourceLocation(PotionsMain.MODID, namePrefix + "_" + typeName);
else
potionTypeName = new ResourceLocation(PotionsMain.MODID, typeName);
return new PotionType(typeName, potionEffects).setRegistryName(potionTypeName);
}
/**
* Создание стандартных рецептов для зелий.
*
* @param standardPotionType
* @param longPotionType
* @param strongPotionType
* @param ingredient
*/
private static void addStandardRecipes(PotionType standardPotionType, PotionType longPotionType, PotionType strongPotionType, Item ingredient) {
PotionHelper.addMix(PotionTypes.AWKWARD, ingredient, standardPotionType);//Аргументы: основа, ингредиент, результат.
if (longPotionType != null)
PotionHelper.addMix(standardPotionType, Items.REDSTONE, longPotionType);
if (strongPotionType != null)
PotionHelper.addMix(standardPotionType, Items.GLOWSTONE_DUST, strongPotionType);
}
/**
* Добавлние своего рецепта.
*
* @param basePotionType
* @param ingredient
* @param outputPotiontype
*/
private static void addRecipe(PotionType inputPotionType, Item ingredient, PotionType outputPotiontype) {
PotionHelper.addMix(inputPotionType, ingredient, outputPotiontype);
}
@SubscribeEvent
public static void registerPotions(RegistryEvent.Register<Potion> event) {
event.getRegistry().registerAll(
EQUILIBRIUM
);
}
@SubscribeEvent
public static void registerPotionTypes(RegistryEvent.Register<PotionType> event) {
event.getRegistry().registerAll(
EQUILIBRIUM_TYPE_STANDARD,
EQUILIBRIUM_TYPE_LONG,
EQUILIBRIUM_TYPE_STRONG
);
}
}
Java:
public class CommonProxy {
public void preInit(FMLPreInitializationEvent event) {}
public void init(FMLInitializationEvent event) {
PotionsRegistry.registerSimpleRecipes();
}
}
Зелье можно будет сварить из основы в виде неловкого зелья и склянки с опытом, продлить редстоуном или усилить светопылью - как в ванили. Регистрируются рецепты в CommonProxy в процессе инициализации.
Дополнительно: зелья в качестве компонента при крафте
Вы можете добавить для варочной стойки рецепт, ингредиентом в котором будет зелье. В исходниках есть рабочий пример, но тут приведу метод регистрации такого рецепта и класс рецепта:
Java:
//Продвинутый рецепт, определённый в собственном классе RecipeRetreatPotion. Используется для создания сложных рецептов, требующих проверки NBT.
BrewingRecipeRegistry.addRecipe(new RecipeRetreatPotion(PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM, 1), VANISH_TYPE_STANDARD), PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM, 1), IRON_SKIN_TYPE), PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM, 1), RETREAT_TYPE)));
Java:
public class RecipeRetreatPotion implements IBrewingRecipe {
private final ItemStack inputStack, ingredientStack, outputStack;
public RecipeRetreatPotion(ItemStack inputStack, ItemStack ingredientStack, ItemStack outputStack) {
this.inputStack = inputStack;
this.ingredientStack = ingredientStack;
this.outputStack = outputStack;
}
@Override
public boolean isInput(ItemStack inputStack) {
boolean isValid = false;
if (inputStack.getItem() == this.inputStack.getItem() && inputStack.hasTagCompound()) {
isValid = PotionUtils.getEffectsFromStack(inputStack).equals(PotionUtils.getEffectsFromStack(this.inputStack));
}
return isValid;
}
@Override
public boolean isIngredient(ItemStack ingredientStack) {
boolean isValid = false;
if (ingredientStack.getItem() == this.ingredientStack.getItem() && ingredientStack.hasTagCompound()) {
isValid = PotionUtils.getEffectsFromStack(ingredientStack).equals(PotionUtils.getEffectsFromStack(this.ingredientStack));
}
return isValid;
}
@Override
public ItemStack getOutput(ItemStack inputStack, ItemStack ingredientStack) {
ItemStack output = ItemStack.EMPTY;
if (this.isInput(inputStack) && this.isIngredient(ingredientStack)) {
output = this.outputStack.copy();
}
return output;
}
}
Для зелий других типов используйте
Items#SPLASH_POTION
и Items#LINGERING_POTION
вместо Items#POTIONITEM
.Если хотите использовать зелье в крафтах на верстаке, то рецепт может выглядеть примерно так (рабочий в исходниках):
Java:
GameRegistry.addShapedRecipe(new ResourceLocation("Utils"), new ResourceLocation("Recipes"), new ItemStack(Items.EXPERIENCE_BOTTLE), new Object[] {" ", " S ", " ", 'S', PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM, 1), PotionsRegistry.EQUILIBRIUM_TYPE_STANDARD)});
Поместив простое зелье из статьи в центр сетки крафта вы получите склянку с опытом.
Всё, на этом туториал завершён. Оставляйте свои комментарии и советы в обсуждении. Спасибо за внимание.