В этой статье описывается создание модификаций на основе Minecraft Forge с использованием Eclipse для версий Minecraft с 1.12.
Для начала работы, создайте папку с названием вашей модификации избегая кириллицы. Если ваш мод имеет название из двух слов, желательно называть папку без пробелов, к примеру 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-битных системах.
Это файл, который задает свойства проекта и его нужно немного подправить:
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": { "pack_format": 3, "description": "Описание вашего мода" } }
Этот файл задаёт более подробную информацию о модификации и заполняется следующим образом:
[{ "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
дав ему имя, идентичное указанному в файле модели.