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

В этой статье описывается создание модификаций на основе Minecraft Forge с использованием Eclipse для версий с 1.10.

## Подготовка среды

- Скачайте и установите
**Eclipse**и**JDK**. Желательно также обновить Java до последней версии, если вы ещё этого не сделали. - Скачайте
**Forge**последней версии (с пометкой**Mdk**в списке) и распакуйте в любую папку. Путь к папке не должен содержать кириллицы. - Произведите декомпиляцию игры:
**Windows**: В папке нажмите`⇧ Shift`+`ПКМ`, выберите "Открыть окно команд" и введите`gradlew.bat setupDecompWorkspace eclipse`

**Linux**: Откройте терминал и введите следующие строки:


cd <путь к папке> ./gradlew setupDecompWorkspace eclipse --refresh-dependencies

- Убедитесь, что декомпиляция прошла успешно. Её процесс должен занять некоторое время и завершиться надписью
**BUILD_SUCCESSFUL**. - Запустите Eclipse. В стартовом окне укажите папку
**eclipse**в папке с Forge.

## Уроки

### Новая модификация

В левой части экрана располагается меню **Package Explorer** (если его там нет, в верхнем меню выберите Window/Show View/Package Explorer), в котором находится папка MDKExample. В этой папке присутствуют две основных папки:

`src/main/java`

— папка с кодом модификации.`scr/main/resources`

— папка для файлов ресурсов (текстуры, звуки, модели и JSON-файлы).

Щёлкните `ПКМ` по папке **src/main/java** и выберите **New/Package**. Укажите название каталога в таком формате:

<домен>.<автор модификации>.<название модификации>

В качестве домена можно использовать любое доменное имя (com, net, ru и т. д.). Например, если ваш никнейм — SomeGuy, а название модификации — SampleMod, полное имя каталога может быть таким:

com.someguy.samplemod

Это имя будет использоваться в дальнейших уроках.

#### Создание классов

После создания каталога щёлкните по нему `ПКМ` и выберите **New/Class**. Этот класс будет основным. Для удобства назовите его `SampleMod`

. В теле класса (после его названия и фигурной скобки) напишите следующий код:

```
public static final String MODID = "samplemod";
public static final String VERSION = "1.0";
```

Над названием класса добавьте строку:

```
@Mod (modid = SampleMod.MODID, version = SampleMod.VERSION)
```

Обратите внимание, что маркер @Mod выделен красным цветом. Это значит, что для него отсутствует библиотека, в которой он объявлен. Чтобы это исправить, наведите на него курсор и выберите `Import 'Mod' (net.minecraftforge.fml.common)`

:

Ещё раз щёлкните `ПКМ` по каталогу и выберите **New/Package**. Создайте каталог `com.someguy.samplemod.proxy`

. В новом каталоге создайте два класса — `ClientProxy`

и `ServerProxy`

.

Дважды щёлкните по классу **ServerProxy** и создайте следующие функции в теле класса:

```
public void preInit (FMLPreInitializationEvent E)
{
}
public void init (FMLInitializationEvent E)
{
}
public void postInit (FMLPostInitializationEvent E)
{
}
```

Если названия типов в скобках выделены красным цветом, по аналогии с предыдущим случаем наводите курсор и нажимайте `Import`

во всех местах.

Теперь перейдите к классу **ClientProxy** и унаследуйте его от **ServerProxy**:

```
public class ClientProxy extends ServerProxy
```

Добавьте те же самые функции с маркером `@Override`

:

```
@Override
public void preInit (FMLPreInitializationEvent E)
{
}
@Override
public void init (FMLInitializationEvent E)
{
}
@Override
public void postInit (FMLPostInitializationEvent E)
{
}
```

Снова перейдите к классу **SampleMod** и напишите в теле класса:

```
@SidedProxy (clientSide = "com.someguy.samplemod.proxy.ClientProxy", serverSide = "com.someguy.samplemod.proxy.ServerProxy")
public static ServerProxy proxy;
```

Если ваша модификация имеет иное название, напишите его вместо `samplemod`

в обоих местах.

Добавьте уже знакомые вам функции в таком виде:

```
@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);
}
```

#### Мета-информация

Основа для вашей модификации готова. Перейдите в папку `src/main/resources`

и откройте файл `mcmod.info`

(при его отсутствии — создайте: `ПКМ`, пункт New/File). Заполните этот файл следующим образом:

```
[
{
"modid": "samplemod",
"name": "Sample Mod",
"description": "Sample Mod description",
"version": "1.0",
"mcversion": "",
"url": "",
"updateUrl": "",
"authorList": ["SomeGuy"],
"credits": "Sample Mod credits",
"logoFile": "",
"screenshots": [],
"dependencies": 
}
]
```

После этого ваша модификация будет отображаться в списке.

Для запуска игрового клиента нажмите зелёную кнопку на верхней панели (). После загрузки вы можете найти модификацию в списке **Mods**.

### Вкладка в творческом режиме

Щёлкните `ПКМ` по каталогу **com.someguy.samplemod** и создайте каталог `com.someguy.samplemod.tab`

. Добавьте в него класс с названием `SampleModTab`

и унаследуйте его от `CreativeTabs`

:

```
public class SampleModTab extends CreativeTabs
```

Название класса стало подчёркнуто красным цветом. Наведите на него курсор и нажмите `Add constructor 'SampleModTab(int, String)'`

и `Add unimplemented methods`

.

Добавьте функцию `preInit`

:

```
public static void preInit ( )
{
}
```

Перейдите к классу **SampleMod** и в самом начале функции **preInit** напишите следующее:

```
SampleModTab.preInit ( );
```

Теперь вы можете добавлять новые вкладки в творческом режиме.

#### Простая вкладка

Снова выберите класс **SampleModTab** и напишите эту строку в начале:

```
public static SampleModTab SAMPLE_MOD;
```

Дополните функцию **preInit** данной строкой:

```
SAMPLE_MOD = new SampleModTab (getNextID ( ), "sample_mod");
```

Функция `getNextID ( )`

автоматически определяет свободный ID вкладки, представленной переменной `SAMPLE_MOD`

.

Обратите внимание на функцию `getTabIconItem`

. Данная функция определяет, какой предмет или блок отображается на вашей вкладке в творческом режиме. Если эта функция выглядит так:

```
public Item getTabIconItem ( )
{
return null;
}
```

Вы можете указать в качестве предмета, например, яблоко, таким образом:

```
public Item getTabIconItem ( )
{
return Items.APPLE;
}
```

Если же вместо `Item`

перед названием указано `ItemStack`

, это делается несколько иначе:

```
public ItemStack getTabIconItem ( )
{
return new ItemStack (Items.APPLE);
}
```

#### Создание нескольких вкладок

Если вам необходимо более одной вкладки, добавьте их по аналогии с первой, инициализируя в функции **preInit**:

```
SAMPLE_MOD = new SampleModTab (getNextID ( ), "sample_mod");
SAMPLE_MOD_NEW = new SampleModTab (getNextID ( ), "sample_mod_new");
```

Во вкладке `SAMPLE_MOD_NEW`

, как и в **SAMPLE_MOD**, будет отображаться тот предмет, который указан в функции **getTabIconItem**. Ниже приведён код этой вкладки с нестандартным предметом (в данном случае — с блоком железа):

```
SAMPLE_MOD_NEW = new SampleModTab (getNextID ( ), "sample_mod_new")
{
public ItemStack getTabIconItem ( )
{
return new ItemStack (Blocks.IRON_BLOCK);
}
};
```

#### Оформление

Возможно, вы заметили, что имя вашей вкладки отображается некорректно. В папке **src/main/resources** создайте каталог `assets.samplemod.lang`

. В этом каталоге вы можете размещать локализации для любого языка, поддерживаемого в текущей версии.

Создайте файл `en_us.lang`

и напишите следующую строку:

```
itemGroup.sample_mod=Sample Mod
```

Теперь ваша вкладка имеет название при выбранном английском языке в настройках.

### Предмет

Щёлкните `ПКМ` по каталогу **com.someguy.samplemod** и создайте каталог `com.someguy.samplemod.item`

. Создайте в этом каталоге класс `SampleModItem`

и добавьте в него несколько методов:

```
public static void preInit ( )
{
addItems ( );
}
public static void addItems ( )
{
}
public static void addRenders ( )
{
}
public static void addItem (Item item, String name)
{
GameRegistry.register (item, new ResourceLocation (SampleMod.MODID, name));
}
public static void addRender (Item item, String name)
{
Minecraft.getMinecraft ( ).getRenderItem ( ).getItemModelMesher ( ).register (item, 0,
new ModelResourceLocation (SampleMod.MODID + ":" + name, "inventory"));
}
```

Перейдите к классу **SampleMod** и добавьте данную строку в функцию **preInit**:

```
SampleModItem.preInit ( );
```

В классе **ClientProxy** добавьте строку в функцию **init**:

```
SampleModItem.addRenders ( );
```

Теперь вы можете добавить в игру любой предмет за несколько шагов.

#### Простой предмет

Создайте переменную в классе **SampleModItem**, представляющую предмет, который вы хотите добавить. К примеру, для предмета с названием "Test Item" напишите в начале класса:

```
public static Item TEST_ITEM;
```

В функции **preInit** перед вызовом функции **addItems** добавьте следующую строку:

```
TEST_ITEM = new Item ( ).setUnlocalizedName ("test_item").setCreativeTab (SampleModTab.SAMPLE_MOD);
```

Вместо **SAMPLE_MOD** вы можете установить любую другую вкладку в творческом режиме, обращаясь к ней через **SampleModTab** или **CreativeTabs**.

Дополните функцию **addItems** этой строкой:

```
addItem (TEST_ITEM, "test_item");
```

Добавьте ещё одну строку в функцию **addRenders**:

```
addRender (TEST_ITEM, "test_item");
```

#### Оформление

Добавьте в файл **en_us.lang** и другие файлы локализации следующую строку:

item.test_item.name=Test Item

Кроме того, вашему предмету нужна текстура. В папке **src/main/resources** создайте каталог `assets.samplemod.models.item`

и добавьте в него файл `test_item.json`

. Скопируйте данный текст в этот файл:

```
{
"parent": "item/generated",
"textures":
{
"layer0": "samplemod:items/test_item"
}
}
```

В этой же папке создайте каталог `assets.samplemod.textures.items`

и разместите в нём вашу текстуру. Пример текстуры: .

### Блок

Щёлкните `ПКМ` по каталогу **com.someguy.samplemod** и создайте каталог `com.someguy.samplemod.block`

. Создайте в этом каталоге класс `SampleModBlock`

и добавьте в него несколько методов:

```
public static void preInit ( )
{
addBlocks ( );
}
public static void addBlocks ( )
{
}
public static void addRenders ( )
{
}
public static void addBlock (Block block, String name)
{
GameRegistry.register (block, new ResourceLocation (SampleMod.MODID, name));
GameRegistry.register (new ItemBlock (block), new ResourceLocation (SampleMod.MODID, name));
}
public static void addRender (Block block, String name)
{
Minecraft.getMinecraft ( ).getRenderItem ( ).getItemModelMesher ( ).register (Item.getItemFromBlock (block),
0, new ModelResourceLocation (SampleMod.MODID + ":" + name, "inventory"));
}
```

Перейдите к классу **SampleMod** и добавьте данную строку в функцию **preInit**:

```
SampleModBlock.preInit ( );
```

В классе **ClientProxy** добавьте строку в функцию **init**:

```
SampleModBlock.addRenders ( );
```

Теперь вы можете добавить в игру любой блок за несколько шагов.

#### Простой блок

Создайте переменную в классе **SampleModBlock**, представляющую блок, который вы хотите добавить. К примеру, для блока с названием "Test Block" напишите в начале класса:

```
public static Block TEST_BLOCK;
```

В каталоге **com.someguy.samplemod.block** создайте класс `BlockTestBlock`

и унаследуйте его от класса `Block`

:

```
public class BlockTestBlock extends Block
```

Добавьте конструктор в таком виде:

```
public BlockTestBlock ( )
{
super (Material.ROCK);
setUnlocalizedName ("test_block");
setCreativeTab (SampleModTab.SAMPLE_MOD);
setHardness (2);
setResistance (1);
}
```

Функция `setHardness`

устанавливает прочность, а `setResistance`

— взрывоустойчивость блока.

Вернитесь к классу **SampleModBlock** и добавьте строку в функцию **preInit** перед функцией **addBlocks**:

```
TEST_BLOCK = new BlockTestBlock ( );
```

Дополните функцию **addBlocks** этой строкой:

```
addBlock (TEST_BLOCK, "test_block");
```

Добавьте ещё одну строку в функцию **addRenders**:

```
addRender (TEST_BLOCK, "test_block");
```

#### Сыпучий блок

Если вам необходимо сделать блок сыпучим, перейдите к его классу и просто унаследуйте его от `BlockFalling`

:

```
public class BlockTestBlock extends BlockFalling
```

При необходимости вы можете изменить звучание блока, делая его схожим с песком или другим материалом. Для этого добавьте в конструктор следующую строку:

```
setSoundType (SoundType.SAND);
```

#### Оформление

Добавьте в файл **en_us.lang** и другие файлы локализации следующую строку:

tile.test_block.name=Test Block

В папке **src/main/resources** создайте каталог `assets.samplemod.models.block`

и добавьте в него файл `test_block.json`

. Скопируйте данный текст в этот файл:

```
{
"parent": "block/cube_all",
"textures":
{
"all": "samplemod:blocks/test_block"
}
}
```

В каталоге **assets.samplemod.models.item** также создайте файл `test_block.json`

следующего содержания:

```
{
"parent": "samplemod:block/test_block"
}
```

Создайте каталог `assets.samplemod.blockstates`

и добавьте в него файл с таким же названием. Скопируйте данный текст в этот файл:

```
{
"variants":
{
"normal": { "model": "samplemod:test_block" }
}
}
```

В этой же папке создайте каталог `assets.samplemod.textures.blocks`

и разместите в нём вашу текстуру.

### Рецепт

Щёлкните `ПКМ` по каталогу **com.someguy.samplemod** и создайте каталог com.someguy.samplemod.recipe. Создайте в этом каталоге класс `SampleModRecipe`

:

```
public static void preInit ( )
{
}
```

По аналогии с предыдущими классами, добавьте строку в функцию **preInit** класса **SampleMod**:

```
SampleModRecipe.preInit ( );
```

#### Рецепт крафта

Добавьте в функцию **preInit** класса **SampleModRecipe** следующий код:

```
GameRegistry.addRecipe (new ItemStack (Blocks.STONE, 1), new Object [ ] {
" A ", "ABA", " A ", 'A', Blocks.CLAY, 'B', Blocks.BEDROCK});
```

Эта строка добавляет в игру такой рецепт:

Ингредиенты | Рецепты крафта |
---|---|

Глиняный блок + Коренная порода |


Каждая буква соответствует указанному блоку или предмету, а в пустых местах ставится пробел. Тип и количество выходного ресурса обозначены в скобках после **ItemStack**.

Этот код добавляет бесформенный рецепт крафта:

```
GameRegistry.addShapedRecipe (new ItemStack (Blocks.STONE, 1), new Object [ ] {
Blocks.CLAY, Blocks.BEDROCK });
```

Ингредиенты | Рецепты крафта |
---|---|

Глиняный блок + Коренная порода |


## Компиляция

Откройте папку с Forge, запустите терминал и введите команду `gradlew.bat build`

. По окончанию процесса ваша модификация появится в папке **build/libs** в скомпилированном виде.