Итак, доброго времени суток. Сегодня мы с вами научимся создавать простейшие моды, используя Forge API.
Что это такое? Forge API - это библиотека, сильно упрощающая создание модов для Minecraft. Плюсы её использования по сравнению с написанием модов без неё:
- относительная простота использования
- совместимость вашего мода с другими модами. В случае написания модов без Forge, скорее всего, на Minecraft ничего, кроме вашего мода, установить не удастся
Этап 1. Подготовка рабочего места
Для начала работы вам понадобится несколько вещей:
- Java Development Kit (JDK). Скачиваете последнюю версию под свою Java здесь
- Среда разработки. Это та самая программа, которая поможет вам работать с многими файлами одновременно и имеет много встроенных вспомогательных компонентов, таких, как Менеджер Пакетов(Package Explorer) и позволяет вам запускать Minecraft с вашим скомпилированным модом "из коробки". Из наиболее популярных:
- Eclipse IDE. Простая, понятная среда разработки. Лично я предпочитаю её. Отлично подойдет для новичков. Язык - английский
- Intellij IDEA. На мой взгляд, она сложнее Eclipse. Впрочем, решать вам. Язык - английский
- NetBeans IDE. Полностью "русская" среда разработки. Как говорится, на ваш вкус и цвет.
Думаю, вы в состоянии найти и скачать какую-нибудь из них. В этом и всех последующих моих туториалах будет использоваться Eclipse.
- Собственно, сама библиотека Minecraft Forge. Скачать Forge нужной версии. Выбираем нужную версию и скачиваем архив с пометкой "src", или "mdk"
Далее, нужно установить сам Forge:
- разархивируем скачанное
- открываем командную строку в вашей операционной системе(PowerShell, Terminal и т.п.)
- переходим в разархивированную папку и запускаем файл gradlew.bat
(для Windows) или gradlew
(для Unix-систем) с аргументами setupDecompWorkspace
. Начнется загрузка множества файлов, деобфускация и декомпиляция кода Minecraft. Подождите окончания процесса установки. После завершения процесса запускаем этот же файл с аргументами eclipse/idea
(в зависимости от вашей среды разработки)
Всё, с подготовкой закончили.
Этап 2. Начало работы.
Итак, у нас всё установлено. Открываем IDE.
1. Главный класс
Для начала нам нужен главный класс. В Package Explorer щелкаем ПКМ по src/main/java
, в открывшемся меню выбираем New -> Package; Называем пакет как вам угодно. Я назову его ru.stannis.tutorial
.
ПКМ по только что созданному пакету -> New -> Class. У главного класса может быть любое название, но лучше и понятнее будет назвать его, как, собственно, мод, который вы создаете.
Итак, мы создали главный класс:
public class Tutorial {
}
Теперь нам надо пометить наш главный класс, чтобы Forge загружал его, как мод:
@Mod(modid="tutorial", name="tutorialmod", version="0.1")
public class Tutorial {
}
Аннотация @Mod
подчеркнется красным. Для исправления импортируйте @Mod
или нажмите сочетание "Organize Imports". В Eclipse это Ctrl + Shift + O
.
Лучше сразу создать константы с нашим MODID, MODNAME и VERSION - авось, потом пригодится.
@Mod(modid=Tutorial.MODID, name=Tutorial.MODNAME, version=Tutorial.VERSION)
public class Tutorial {
public static final String MODID = "tutorial";
public static final String MODNAME = "tutotialmod";
public static final String VERSION = "0.1";
Для последующего использования добавим внутреннюю ссылку на наш мод. Вставим внутри класса:
@Instance
public static Tutorial instance = new Tutorial();
Далее для регистрации вещей, блоков, ивентов, мобов и прочего, что будет добавлять наш мод, нам нужны методы, вызывающиеся на разных стадиях инициализации Forge. В главный класс добавляем:
@EventHandler
public void preInit(FMLPreInitializationEvent e) {
}
@EventHandler
public void init(FMLInitializationEvent event) {
}
@EventHandler
public void postInit(FMLPostInitializationEvent e) {
}
Всё, заготовка есть.
2. Прокси
Прокси(Proxy) - это инструмент в Minecraft Forge, позволяющий отделить в моде то, что для сервера от того, что для клиента. Ну и является удобным способом получения EntityPlayer
отправителя пакета при обработке пакета.
Создаем пакет для прокси. У меня это ru.stannis.tutorial.proxy
. Там создаем класс CommonProxy:
public class CommonProxy {
}
Добавляем в него наши ивенты инициализации мода:
public class CommonProxy {
public void preInit(FMLPreInitializationEvent e) {
}
public void init(FMLInitializationEvent event) {
}
public void postInit(FMLPostInitializationEvent e) {
}
}
Не забываем импортировать недостающие классы.
Теперь создадим классы ClientProxy, ServerProxy и сделаем их расширяющими класс CommonProxy;
public class ClientProxy extends CommonProxy {
@Override
public void preInit(FMLPreInitializationEvent e) {
}
@Override
public void init(FMLInitializationEvent event) {
}
@Override
public void postInit(FMLPostInitializationEvent e) {
}
}
public class ServerProxy extends CommonProxy {
@Override
public void preInit(FMLPreInitializationEvent e) {
}
@Override
public void init(FMLInitializationEvent e) {
}
@Override
public void postInit(FMLPostInitializationEvent e) {
}
}
Отлично! Теперь мы можем зарегистрировать прокси. Для этого добавляем в главный класс:
@SidedProxy(clientSide="ru.stannis.tutorial.proxy.ClientProxy", serverSide="ru.stannis.tutorial.proxy.ServerProxy")
public static CommonProxy proxy;
В clientSide
вписываем полный путь до ClientProxy
, в serverSide
- до ServerProxy
.
И, наконец, используем прокси:
@Mod(modid=Tutorial.MODID, name=Tutorial.MODNAME, version=Tutorial.VERSION)
public class Tutorial {
public static final String MODID = "tutorial";
public static final String MODNAME = "tutotialmod";
public static final String VERSION = "0.1";
@Instance
public static Tutorial instance = new Tutorial();
@SidedProxy(clientSide="ru.stannis.tutorial.proxy.ClientProxy", serverSide="ru.stannis.tutorial.proxy.ServerProxy")
public static CommonProxy proxy;
@EventHandler
public void preInit(FMLPreInitializationEvent e) {
proxy.preInit(e);
}
@EventHandler
public void init(FMLInitializationEvent e) {
proxy.init(e);
}
@EventHandler
public void postInit(FMLPostInitializationEvent e) {
proxy.postInit(e);
}
}
Всё. Теперь у нас и прокси есть.
3. Первый блок.
Проще всего - добавить блок. Это мы сейчас и сделаем.
Создаем пакет для блоков. У меня - ru.stannis.tutorial.blocks
.
Там создаем класс для нашего блока, расширяющий класс Block:
public class TutorialBlock extends Block {
}
Создадим конструктор для блока и укажем его параметры:
public TutorialBlock() {
super(Material.rock);
this.setUnlocalizedName("tutorialblock"); //установка нелокализированного имени блока
this.setCreativeTab(CreativeTabs.tabBlock); // установка вкладки креатива, в которой будет наш блок
this.setStepSound(Block.soundTypeGrass); // звук, проигрывающийся при прохождении по блоку
this.setHarvestLevel("pickaxe", 2); // инструмент для добычи и его уровень(0 - деревянный, 1 - каменный, 2 - железный, 3 - алмазный)
this.setHardness(10.0F);
this.setResistance(100.0F); // устойчивость к взрывам
}
Хорошо, блок создан. Теперь мы должны его зарегистрировать. В главном классе до всех функций создаем объект нашего блока:
public static Block tutorialBlock;
И регистрируем блок:
public void init(FMLInitializationEvent e) {
GameRegistry.registerBlock(tutorialBlock = new TutorialBlock(), "tutorialBlock");
}
Хорошо, блок мы зарегистрировали. Теперь нужно зарегистрировать модель блока.
Создаем пакет для функций рендера - ru.stannis.tutorial.client.render
. В него добавляем класс RenderRegister
с функцией регистрации моделей блока и функцией регистрации одной модели:
public class RenderRegister {
public static void registerBlockRenderer() {
}
public static void registerBlockModel(Block block) {
Minecraft.getMinecraft().getRenderItem().getItemModelMesher()
.register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(Tutorial.MODID + ":" +
block.getUnlocalizedName().substring(5), "inventory"));
}
}
И, наконец, зарегистрируем модель:
public static void registerBlockRenderer() {
registerBlockModel(Tutorial.tutorialBlock);
}
Теперь включим наш класс в мод - вызовем registerBlockRenderer
в ClientProxy
:
@Override
public void init(FMLInitializationEvent e) {
RenderRegister.registerBlockRenderer();
}
Ура, мы зарегистрировали модель. Однако и это еще не всё. Самой модели - то нет...
Создаем в папке java/main/resources
пакет для моделей блоков. Он обязательно должен выглядеть так: assets.your_modid.models.block
. Далее создаем пакет для BlockStates: assets.your_modid.blockstates
. Имеет смысл также создать пакет для текстур блоков: assets.your_modid.textures.blocks
Модели в Minecraft описываются файлами в формате Json. Также есть возможность отрисовки моделей OBJ.
Сложные модели блоков можно создавать в программах ModelCreator, Blender, Techne.
Простые модели наследуют строение моделей-родителей, и в них нужно указывать только текстуры для наложения. Простая модель - обычный строительный блок с одной текстурой, которая накладывается со всех его сторон:
{
"parent": "cube/all", // модель, от которой идёт наследование
"textures": {
"all": "tutorial:blocks/tutorialBlock" // текстура
}
}
Осталось последнее - создать файл BlockState. Это тоже файл в формате Json. Содержимое файла BlockState говорит клиенту, какую модель рисовать на месте блока в зависимости от состояния блока(например, поворот его) или места рендера(на земле, в GUI).
{
"normal": { "model": "tutorial:tutorialBlock" },
"inventory": { "model": "tutorial:tutorialBlock" }
}
Соответственно, закидываем текстуру в пакет для текстур, и запускаем мод из среды разработки. Видим наш блок во вкладке для блоков и радуемся.
4. Предмет
Итак, блок мы создали. Пришло время создать предмет.
Создаем пакет для предметов - ru.stannis.tutorial.items
. В нем создаем класс для предмета:
public class TutorialItem extends item {
}
Внутри класса добавляем конструктор:
public TutorialItem() {
this.setUnlocalizedName("TutorialItem"); // нелокализированное имя
this.setCreativeTab(CreativeTabs.tabMisc); // вкладка креатива
this.setMaxStackSize(32); // максимальное кол-во нашего предмета в стаке(1-64)
this.setMaxDamage(540); // прочность предмета
}
Теперь нужно зарегистрировать модель предмета. Создаем в нашем классе RenderRegister
функцию registerItemRenderer
и registerItemModel
:
public static void registerItemRenderer() {
}
public static void registerItemModel(Item item) {
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, 0, new
ModelResourceLocation(Tutorial.MODID + ":" + item.getUnlocalizedName().substring(5), "inventory"));
}
Зарегистрируем модель:
public static void registerItemRenderer() {
registerItemModel(Tutorial.TutorialItem);
}
Теперь надо бы зарегистрировать предмет.
В главном классе заводим переменную типа Item
:
public static Item TutorialItem;
Регистрируем предмет в методе init
главного класса:
GameRegistry.registerItem(TutorialItem = new TutorialItem(), "TutorialItem");
И добавляем метод регистрации моделей предметов в ClientProxy.init
:
RenderRegister.registerItemRenderer();
Создаем в src/main/resources
пакет для моделей предметов - assets.tutorial.models.item
И пакет для текстур предметов - assets.tutorial.textures.items
.
Закидываем туда модель, текстуру, запускаем Minecraft и радуемся нашему предмету.
Добавление лора к предметам.
Для добавления описания к предмету необходимо переопределить функцию addInformation
в классе предмета:
@Override
public void addInformation(ItemStack itemStack, EntityPlayer player, List list, boolean par4) {
list.set(1, "ваша_строка_в_лоре_предмета"); // первая стока в лоре предмета
. . .
}