Создание модификаций с помощью Forge/1.12+

Материал из Minecraft Wiki
Перейти к: навигация, поиск

В этой статье описывается создание модификаций на основе 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 для его иконки в инвентаре. Поэтому для начала создадим файл blockstate, который и подключит наши модели.

{
  "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 дав ему имя, идентичное указанному в файле модели.