В этой статье описывается создание модификаций на основе Minecraft Forge с использованием Eclipse для версий Minecraft с 1.12.
Установка Forge Gradle[]
Для начала работы, создайте папку с названием вашей модификации избегая кириллицы. Если ваш мод имеет название из двух слов, желательно называть папку без пробелов, к примеру Tutorial-Mod или TutorialMod. Далее перейдите на официальный сайт Forge и скачайте версию с пометкой MDK (Modder Development Kit). Из загруженного архива извлеките папку gradle и файл build.gradle в папку модификации, остальные файлы сохранены для совместимости и/или дополнительных функций и для начала не понадобятся. Далее импортируйте в Eclipse проект как Existing Gradle Project указав папку модификации. Затем в колонке Gradle tasks поочерёдно выполните setupDecompWorkspace из набора forgegradle и eclipse из набора ide (Для пользователей IntelliJ IDEA task genIntelliJRuns), и обновите среду (ПКМ по проекту и Refresh). Теперь можно удалить два файла с расширением .launch, так как для тестовых запусков мы будем использовать задачи Gradle. Для настройки папок ресурсов создайте в папке проекта два каталога: src\main\java и src\main\resources после чего выделите их и по ПКМ найдите пункт Build Patch и нажмите Us as source folder.
Не забудьте! Далее, все связанное с Java кодом мы будем делать в каталоге src\main\java, а остальное в src\main\resources.
Примечание! Для установки потребуется компьютер с минимальным объёмом ОЗУ от 4Гб! Если у вас недостаточно ОЗУ, добавьте необходимый объём из файла подкачки, но такой метод работает лишь на 64-битных системах.
Создание модификации[]
build.gradle[]
Это файл, который задает свойства проекта и его нужно немного подправить:
buildscript {
repositories {
jcenter()
maven {
url = "http://files.minecraftforge.net/maven"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
}
}
apply plugin: 'net.minecraftforge.gradle.forge'
version = "версия_модификации" //Обычно согласно версии major.minor.patch
group = "пакет_главного_класса" //Обычно в стиле домен.автор.идентификатор_модификации
archivesBaseName = "идентификатор_модификации" //Без пробелов и только в нижнем регистре
sourceCompatibility = targetCompatibility = '1.8'
compileJava {
sourceCompatibility = targetCompatibility = '1.8'
}
minecraft {
version = "1.12.2-14.23.5.2768"
runDir = "run"
mappings = "snapshot_20171003"
}
dependencies {
}
processResources {
inputs.property "версия_модификации", project.version
inputs.property "1.12.2", project.minecraft.version
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
expand 'version':project.version, 'mcversion':project.minecraft.version
}
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}
runClient {
args "--username=НикнеймАвтора"
jvmArgs "-Xms2G", "-Xmx2G", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseG1GC", "-XX:G1NewSizePercent=20", "-XX:G1ReservePercent=20", "-XX:MaxGCPauseMillis=50", "-XX:G1HeapRegionSize=32M"
}
runServer {
jvmArgs "-Xmx2G", "-Xmx2G"
}
Если вы используете IntelliJ IDEA, то в конец build.gradle дополнительно добавьте это:
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = true
}
}
subprojects {
apply plugin: 'idea'
}
task prepareAssets(type: Copy) {
group = 'build'
from project.file('src/main/resources')
into project.file('build/classes/java/main')
}
classes.dependsOn(prepareAssets)
pack.mcmeta[]
Этот файл нужен для корректной работы игры с ресурсами модификации, такими как локализации, модели, рецепты, таблицы добычи и так далее. Заполняется следующим образом:
{
"pack": {
"pack_format": 3,
"description": "Описание вашего мода"
}
}
mcmod.info[]
Этот файл задаёт более подробную информацию о модификации и заполняется следующим образом:
[{
"modid": "Идентификатор модификации",
"name": "Название",
"description": "Описание",
"version": "${version}",
"mcversion": "${mcversion}",
"logoFile": "Путь к логотипу",
"url": "Сайт модификации",
"authorList": ["Автор"],
"credits": "Благодарности кому либо"
}]
Класс модификации[]
Данный класс создается в патче и является главным файлом, благодаря которому игра видит нашу модификацию. Заполняется следующим образом:
@Mod(modid = "идентификатор", name = "название", version = "${version}", dependencies = "required-after:forge@[минимальная версия forge,)", useMetadata = true)
public class TutorialMod {
}
Блок[]
Класс блока[]
Для создания блока создайте класс с названием блока в стиле TutorialBlock в пакете патч.blocks и заполните его следующим образом:
public class TutorialBlock extends Block {
public TutorialBlock() {
super(Material.Материал); //Задает звук ходьбы, к примеру Rock или Glass
this.setCreativeTab(CreativeTabs.ВкладкаТворчества); //К примеру BuildingBlocks
this.setHardness(прочность_блока); //К примеру 3.0F как у руд
this.setResistance(взрывоустойчивость_блока); //К примеру 15.0F как у руд
this.setHarvestLevel("инструмент", уровень); //К примеру pickaxe и 0 как деревянная кирка
this.setRegistryName("идентификатор_блока"); //Используется для подключения моделей и в команде /give
this.setUnlocalizedName("ключ_локализации"); //Можно использовать идентификатор блока
}
}
Примечание регистрируемое имя и ключ локализации указывать только в нижнем регистре, используя при надобности нижнее подчёркивание!
Модель[]
Модель (которую, например, можно создать здесь) решает то, как наш блок будет выглядеть. Важно знать, что для блоков используется две модели. Одна задает вид блока, поставленного в мире, а вторая, его иконку в инвентаре. Это дает нам возможность сделать блоку отдельную иконку для инвентаря. Сами же модели для блока подключаются к нему как состояния, normal для блока в мире и inventory для его иконки в инвентаре. Поэтому для начала создадим файл идентификатор_блока.json в пакете assets.идентификатор_мода.blockstates, который и подключит наши модели.
{
"variants": {
"normal": { "model": "идентификатор_мода:идентификатор_блока" }
}
}
Теперь подключим модели. Для этого создайте файл регистрируемое_имя.json в пакете assets.идентификатор_мода.models.block со следующим содержимым:
{
"parent": "block/cube_all",
"textures": {
"all": "идентификатор_мода:blocks/идентификатор_блока"
}
}
Теперь зададим иконку блока в инвентаре в пакете assets.идентификатор_модификации.models.block с именем идентификатор_блока.json со следующим содержанием:
{
"parent": "идентификатор_мода:block/идентификатор_блока"
}
Регистрация[]
Наш блок имеет текстуры и свойства, но его нужно зарегистрировать в игре. Создадим в пакете домен.автор.мод.init
класс BlocksInit
:
public static Block ВАШ_БЛОК = new BlockИмяБлока();
public static void registerBlocks() {
setRegister(ВАШ_БЛОК);
}
@SideOnly(Side.CLIENT)
public static void registerBlocksRender() {
setRender(ВАШ_БЛОК);
}
private static void setRegister(Block block) {
ForgeRegistries.BLOCKS.register(block);
ForgeRegistries.ITEMS.register(new ItemBlock(block).setRegistryName(block.getRegistryName()));
}
@SideOnly(Side.CLIENT)
private static void setRender(Block block) {
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory"));
}
Теперь в главном классе в методе preInit
добавьте инструкцию BlocksInit.registerBlocks
а в методе init
BlocksInit.registerBlocksRender
.
Предмет[]
Основное[]
Класс предмета[]
Для создания предмета создадим класс с именем TutorialItem:
import net.minecraft.item.Item;
public class TutorialItem extends Item
{
public TutorialItem(String string) //Параметр string будет заполняться в регистраторе
{
this.setUnlocalizedName(string); //Имя предмета если нет файла локализации
this.setRegistryName(string); //Имя в регистре игры, также используется в команде /give
this.maxStackSize(целое число от 1 до 64); //Размер стопки для предмета, по умолчанию 64
this.setCreativeTab(вкладка); //Творческая вкладка, где будет размещен предмет, пример: this.setCreativeTab(CreativeTabs.MISC);
this.setHasSubtypes(true или false); //Используется для обозначения, что у предмета есть подтипы, т.е. метадата
}
}
Регистрация[]
Для регистрации предмета создадим класс ItemsRegister:
public class ItemsRegister
{
public static Item ВАШ_ПРЕДМЕТ = new TutorialItem("item_tutorial");
public static void register()
{
setRegister(ВАШ_ПРЕДМЕТ);
}
@SideOnly(Side.CLIENT)
public static void registerRender()
{
setRender(ВАШ_ПРЕДМЕТ);
}
private static void setRegister(Item item)
{
ForgeRegistries.ITEMS.registerAll(item);
}
@SideOnly(Side.CLIENT)
private static void setRender(Item item)
{
Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory"));
}
}
В классе CommonProxy, в методе preInit()
добавляем строку ItemsRegister.register();
, а в методе init()
ItemsRegister.registerRender();
.
Модель[]
Теперь у нас есть предмет, однако если мы запустим игру и выдадим себе его, то он будет выглядеть как куб с фиолетовыми и черными клетками. Это говорит о том, что игра не нашла модель предмета. Для исправления этой проблемы создаём в папке src/main/resources/assets/имя_мода/models/item
файл с расширением .json и пишем в нём следующий текст:
{
"parent": "item/generated",
"textures": {
"layer0": "имя_мода:items/имя_текстуры"
}
}
Либо
{
"parent": "item/handheld",
"textures": {
"layer0": "имя_мода:items/имя_текстуры"
}
}
Примечание: название файла модели должно совпадать с RegistryName предмета
Второй вариант используется для моделей инструментов и оружия. Однако теперь, когда у нас есть модель для предмета, осталось добавить текстуру по пути src/main/resources/assets/имя_мода/textures/items
дав ему имя, идентичное указанному в файле модели.