Создание модификаций с помощью Forge/1.7+/Основные уроки

Здесь представлены основные уроки по созданию модификаций с помощью Forge/1.7+. Остальную информацию по данной теме смотрите в соответствующей статье.

## Урок 1. Директория Eclipse (Установка среды)

Теперь вы можете приступать к созданию своей первой модификации.

Заранее придумайте название своей модификации (например, MyBestMod). Перейдём к тому, где должна быть модификация в структуре классов Minecraft. Существует некоторый этикет, как оформлять код и всё, что с ним связано. Раскройте проект Minecraft, далее `src/main/java`

. В `src/main/java`

лежит всё, что относится к коду Minecraft. Как вы видите, там есть подпапки (или пакеты) типа net.minecraft.client[1] и так далее. В Java пакетах принято структурировать пакеты так: `domain.product`

или `domain.company.product`

, то есть первое — домен (com, net, ru), далее название компании (если вы единственный разработчик — ваш ник) и название продукта (модификации), или же название компании опускается.[2][3] Minecraft, Minecraft Forge и FML имеют первый вариант структурирования пакета. То есть, если ваш никнейм, например, platon, а название вашей модификации — My Best Mod, то нажмите на src/main/java `ПКМ` и выберите New → package. В поле «Name» наберите «com.platon.mybestmod» с учётом регистра. Это создаст директорию, в которой вы и будете работать с модификацией. Всё, далее можете приступать непосредственно к его созданию.

## Урок 2. Главный класс

Итак, можно приступить к созданию модификации. Создадим его основу.

Нажмите `ПКМ` на директории модификации (com.platon.mybestmod) и выберите New → Class, и в поле Name введите название класса. Это главный класс модификации, поэтому пусть это будет указано. Например, одно из возможных названий — «BaseMyBestMod». Обратите внимание, что каждое слово написано с большой буквы (естественно, именно так делать необязательно, но общепринятым считается именно этот вариант). Далее просто нажмите Finish. Всё, у вас теперь есть главный класс модификации.

Приступим к написанию кода. Запишем ВНЕ тела, то есть над строчкой `public class... `

[4] класса следующую строчку:

```
@Mod (modid = "mybestmod", name="My Best Mod", version = "1.0")
```

Вы написали, что ваша модификация называется «My Best Mod» и имеет версию 1.0. Но Eclipse сообщает об ошибке, так как ему неизвестно, что значит @Mod. Нужно импортировать соответствующий класс, для этого после строчки с указанием пакета (`package platon.mods.mybestmod;`

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

```
import cpw.mods.fml.common.Mod;
```

После этого сообщение об ошибке должно исчезнуть.

Далее уже в теле (в фигурных скобках) пишем:

```
@EventHandler
public void preLoad(FMLPreInitializationEvent event)
{
}
```

Опять ошибка. Как вы поняли, ему опять не хватает импортированных классов. Почти всегда можно автоматически их импортировать, если Eclipse знает или догадывается, где их искать[5].

Вот и всё. Основа модификации готова. Можете запустить Minecraft (Зеленая кнопка сверху → Client) и увидеть в списке модификаций свою модификацию. По крайней мере для того, чтобы приступить к созданию первого блока.

## Урок 3. Блок

Приступим к созданию своего первого собственного блока.

В самом начале тела Класса (После первой фигурной скобки если вы ещё не поняли) пишем:

```
public static Block bestblockever;
```

Public значит, что объект bestblockever (такое кодовое имя мы дали блоку) может быть вызван откуда угодно. Static, что он статичный, а Block значит тип объекта. А вот описание объекта Block надо импортировать, так как в нашем классе этого не указано. Для этого нажмем по ошибке и выберите импорт из `net.minecraft.block`

, а не откуда либо ещё. В случаях с множественными вариантами импорта `Ctrl-Shift-O` лучше не нажимать. Всё, ошибка исчезла.

Теперь укажем, где про блок будет написано более подробно. В теле метода preLoad() напишем строчку:

```
bestblockever = new BlockBestBlockEver();
```

Эта строка говорит, что про объект bestblockever будет написано в классе BlockBestBlockEver. И он выдаёт ошибку. Естественно, ведь никакого класса BlockBestBlockEver не существует. Его легко создать, нажав по ошибке и выбрав Create Class… Далее нажмите Finish.

Вы перейдете сразу в созданный вами класс. Сразу после названия класса перед фигурной скобкой допишите extends Block. Первую ошибку исправьте, импортировав недостающий класс Block (net.minecraft.block). Вторую ошибку вы видите, потому что созданный класс — наследник класса Block в котором написано что такое блок. И не хватает аргументов которые нужно дать тому классу, чтобы ваш блок был особенным. материал, прочность и т. д. Поэтому просто исправьте ошибку первым способом, он сам её исправит, дописав немного. Строку с двумя слешами, комментарий, можно стереть[6].

В скобках у объекта, где написаны аргументы, которые должны быть посланы снаружи уберите аргумент Material par1Material. Мы пошлем его отсюда, а не снаружи класса. Теперь в следующей строчке в скобках у super() замените «par1Material» на «Material.rock», или после точки сами выберите нужный вам материал.(Не забудьте про импорт) То есть мы посылаем в суперкласс Block что материал блока камень. То есть блок как камень: на звук как камень, ломается с тем же звуком и т. д. Список доступных материалов можно посмотреть через точку после Material.

Итак, давайте поработаем над характеристиками блока. Это можно сделать из главного класса, указывая их через точку после `bestblockever = new BlockBestBlockEver();`

(до точки с запятой). Но можно и отсюда. Для этого пишите их в теле этого объекта после «this.» также можно не писать.

Основные характеристики:

```
this.setBlockName("bestblockever");
// Без этой строчки у блока не будет внутриигрового (нелокализированного) имени, он просто будет называться «null».
this.setCreativeTab(CreativeTabs.tabBlock);//
// Указывает в какой вкладке будет находиться блок в креативе (доступные также можно посмотреть через точку от CreativeTabs). Не забудьте про импорт.
this.setHardness(15F);
// Устанавливает прочность, то есть как долго блок будет ломаться.
this.setResistance(10F);
// Устанавливает взрывоустойчивость блока.
this.setHarvestLevel("pickaxe", 3);
// Устанавливает, киркой какого уровня можно сломать. Например, алмазная = 3.
```

Также можно установить будет ли блок светиться. Чем больше число, тем светлее. Вместо 0 пишете уровень света, создаваемого блоком, умноженное на 10. Таким образом нужно вставить туда значение от 0 до 150 (150 означает уровень света 15, максимальное значение).

```
this.setLightLevel(0F);
```

Теперь давайте добавим текстуру блоку. Она может быть любой, но размером 16×16 или 32х32 пикселей. Например можно создать картинку, написать в ней «Б» и уменьшить до 16×16 пикселей и чуть-чуть подредактировать. Можете скачать эту: Желательно, чтоб название было как у блока, а расширение обязательно .png

Так, текстура есть, теперь пропишем её в код. Следующее пропишите всё в том же методе блока.

```
this.setBlockTextureName("mybestmod:BlockBestBlockEver");
```

Давайте немного разберемся насчёт «mybestmod:BlockBestBlockEver». Должно быть написано «краткое название модификации: название файла», но название без .png. **ВАЖНО! Для пользователей IntelliJ IDEA** — ide автоматически склеивает названия папок как ей вздумается, но чтобы работало подключение ресурсов физическая структура папок должна быть строго такой: assets/mymod/textures/blocks — то есть это отдельные папки! Если создавать через New -> Directory и указать «assets.mymod» — она НЕ создаст отдельные подпапки и работать не будет!

Теперь поместим текстуру в проект. Слева в окне директорий проекта выберите `src/main/resources`

и нажмите правой кнопкой и создайте директорию.(New → package) Назовите так: assets.краткое название модификации.textures.blocks (assets.mybestmod.textures.blocks). Теперь мышкой перетяните текстуру из windows в эту директорию. В окне выберите «Copy files».

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

```
GameRegistry.registerBlock(bestblockever, "bestblockever");
```

Это должно зарегистрировать блок в Forge.

Начиная с версии 1.9, блоки регистрируются в два этапа. О том, как это сделать, можно посмотреть здесь

И последнее: мы не указали, как будет называться блок в игре. Локализация описана в этом доп. уроке.

Ну вот и всё, блок создан. Теперь необходимо проверить его работоспособность. Запускайте Minecraft с вашей модификацией! Но сначала сохраните оба класса (`Ctrl-S`). Для запуска нужно нажать сверху зелёный круг с треугольником (или `Ctrl-F11`). После запуска посмотрите, есть ли ваша модификация в списке модификаций (в главном меню), создайте новый мир в режиме креатив и найдите свой блок в креатив-инвентаре во вкладке блоки. Если он там есть, берется, ставится и ломается, то поздравляю: модификация, добавляющая блок, создана!

## Урок 4. Предмет

Ну вот мы и создали блок. Но ведь в игре присутствуют не только блоки, но и предметы. Такие как еда, инструменты, в общем всё подряд, что обычно нельзя поставить на землю. Давайте создадим такой предмет. Для примера возьмём кирку.

Перейдем в главный класс модификации. До метода preLoad() сразу после `public static Block bestblockever;`

допишите:

```
public static Item bestpickaxe;
```

Тем самым мы создадим переменную типа Item с кодовым названием кирки.

В методе preLoad() для удобства отступите одну строку от того что уже написано, и пишите туда следующее: (Я сразу напишу всё, что нужно, многие элементы описания предмета совпадают с описанием блока, особой разницы нет)

```
bestpickaxe = new BestPickAxe().setUnlocalizedName("bestpickaxe");
GameRegistry.registerItem(bestpickaxe, "bestpickaxe");
```

Итак, мы создали кирку, дали ей нелокализированное имя[7] и зарегистрировали в Forge. Щелкнув по ошибке создадим класс этой кирки. Класс создан, но Eclipse не знает, что мы хотим создать — еду или инструмент, поэтому сделаем этот класс наследником класса, где написано про инструмент или еду или что хотите, главное, что про предмет, а не блок. В строчке `public class BestPickAxe{`

после BestPickAxe допишите `extends ItemPickaxe`

и импортируйте этот самый ItemPickaxe.

Немного об ItemPickaxe: **pickaxe** — это кирка по-английски, и, соответственно, `extends ItemPickaxe`

говорит о том, что мы «продолжаем» или дополняем класс ItemPickaxe, в котором указаны все базовые характеристики и функции, такого Item’а или предмета, как кирка. Таким образом можно продолжать любой класс, в зависимости от того, какой предмет нужен. То есть, если нужна еда, то мы продолжаем класс ItemFood, если броня, то ItemArmor, а если свой особенный предмет, то просто Item. Не забывайте: вы всегда можете посмотреть список возможных продолжений того, что вы пишете.[8]

Теперь, не обращая внимания на появившуюся ошибку вставьте в тело это:

```
protected BestPickAxe() {
super(ToolMaterial.EMERALD);
}
```

Тогда ошибка исчезнет. Строка `super(ToolMaterial.EMERALD);`

говорит о том, что пошлёт в супер-класс информацию о том, что кирка обладает свойствами алмазной кирки. Ну и также допишем после этой строчки

```
this.setCreativeTab(CreativeTabs.tabTools);
```

тем самым добавив кирку в раздел инструменты в режиме «Творчество».

Почти готово. осталось только добавить текстуру, давайте модифицируем текстуру из Minecraft. Зайдите в папку c Minecraft\versions\1.7.2, там откройте jar-файл c помощью архиватора, в архиве перейдите в assets\items и там найдите какую-нибудь текстуру кирки, извлеките на рабочий стол. Файлы текстур НЕЛЬЗЯ редактировать обычным Paint’ом, так как текстура должна быть кое-где прозрачной, если вы не хотите конечно идеально квадратную кирку. В общем отредактируйте текстуру как угодно, главное чтоб была 16×16. Назовите текстуру BestPickAxe.png Теперь создайте в проекте директорию с текстурами предметов. Для этого `ПКМ` по src → New → package а в названии напишите `assets.mybestmod.textures.items`

и туда мышью с раб. стола перенесите готовую текстуру и нажмите ОК. Теперь скажем предмету где его текстура. Пропишите следующее всё в том же методе кирки.

```
this.setTextureName("mybestmod:BestPickAxe");
```

И можно запускать для проверки.

Собственно вот мы и создали первый предмет — инструмент — кирку, которая по свойствам, как алмазная. В этом доп. уроке вы можете посмотреть, как создать инструмент с особыми свойствами.

## Урок 5. Крафт

Если Вы создаёте модификацию исключительно для добавления/удаления рецептов уже существующих вещей, то следует также рассмотреть вариант использования MineTweaker.

Собственно, у нас есть блок и предмет. Мы можем их держать в руках, а блок даже ставить. Но а если мы хотим достать их, играя в режиме Выживания? Тогда блок или предмет можно только найти или скрафтить. Добавить крафт очень просто. Предположим, рецепт блока должен быть следующим:

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

Гравий + Железный слиток + Обсидиан |


Тогда я запишу вот это в тело метода preLoad главного класса **после** строки регистрации блока в Forge:

```
GameRegistry.addRecipe(new ItemStack(BaseMyBestMod.bestblockever, 1),
new Object[]{
"###", "XYX", "###",
('X'), Blocks.gravel,
('#'), Items.iron_ingot,
('Y'), Blocks.obsidian
}
);
```

Давайте разберем, что тут написано: Итак с помощью GameRegistry мы добавляем новый рецепт, new itemStack значит, что создастся новая стопка с предметом bestblockever который объявлен в классе BaseMyBestMod в количестве одной штуки (вместо 1 можно вписать любое число до 64). А далее уже записана сетка крафта. Как мы помним в верстаке мы видим всего 9 клеток, здесь первая строка верстака это «###», вторая строка — это «XYX», ну и последняя — «###». Понятней будет, если посмотреть вот так:

"###" "XYX" "###"

Каждый предмет в крафте обозначается своим личным знаком (любым). Далее это записано как `('X'), Blocks.gravel`

То есть это означает, что X — это гравий, который является блоком. Соответственно знак # — это слиток железа (который является предметом, а не блоком), а Y — это блок обсидиана. Если нужно, чтоб в ячейке крафта ничего не лежало, то вместо знака пишется пробел (Например " # " значит что посередине будет слиток железа, а по бокам ничего).

Добавить рецепт крафта можно не только вашему блоку или предмету. Можно вписывать вместо `BaseMyBestMod.bestblockever`

или `Blocks.obsidian`

что угодно, главное что бы после точки была указана зарегистрированная переменная типа Block или Item. А до точки — это просто путь к этой переменной.

Если хотите создать крафт, который можно произвести в инвентаре, вместо «###», «XYX», «###» используйте «AA», «BC» соответственно.

Бесформенный крафт (то есть крафт, в котором можно располагать ингредиенты как угодно) опишите так:

```
GameRegistry.addShapelessRecipe(new ItemStack(Blocks.grass, 4), new Object[] {Blocks.gravel, Blocks.gravel, Items.arrow});
```

То есть если вы положите в верстак/инвентарь 2 блока гравия и стрелу, то получите 4 блока Земли, покрытой травой.

Если у блока/предмета есть несколько видов (например: дубовые, еловые, березовые доски и т. д.), то указав просто например: `Blocks.Planks`

в крафте можно будет использовать любые доски! Что бы это исправить вместо `Block.Planks`

напишем `new ItemStack(Blocks.planks, 1, 0)`


Первое число всегда 1. Изменяем только второе число. 0 — это дубовые доски, 1 — еловые доски и т. д. (см. ID)

```
GameRegistry.addRecipe(new ItemStack(MuchBlocks.MyBlockS, 1),
new Object[]{ " I ", "IPI", " I ",
('I'), Items.iron_ingot, ('P'), new ItemStack(Blocks.planks, 1, 0)}
);
```

Так же в игре, как мы знаем, присутствует переплавка одних предметов/блоков в другие. Рецепт такой переплавки создаётся всего одной строкой, которую нужно писать после регистрации блока bestblockever:

```
GameRegistry.addSmelting(bestblockever, new ItemStack(Blocks.diamond_block, 2), 1.0F);
```

Но теперь разберём. Итак, первой в скобках указана переменная типа Block (также можно Item), в данном случае это наш блок, затем идет переменная типа ItemStack, которая создаётся сразу же. У этой переменной уточняется, что создастся стак с блоком или предметом, в данном случае алмазным блоком, в количестве 2. Ну и последняя переменная отвечает за количество опыта, получаемого при переплавке.

Собственно, всё.

## Урок 6. Компиляция

Что же, вы написали модификацию, она работает, но вы хотите чтобы он работал и просто на Minecraft. Давайте наконец его скомпилируем!

Компилировать модификацию очень просто, запустите файл gradlew.bat с командой build. Или другими словами создайте bat-файл (или измените оставшийся) с кодом:

gradlew.bat build

и запустите его. После автоматического закрытия консоли модификация скомпилирована и находится в папке build/libs. Если для компиляции модификации требуется подключение дополнительных jar библиотек, то необходимо в корневой папке проекта (MCModding) создать папку libs и поместить все необходимые файлы в неё.

Теперь немного о том, что получилось. У нас есть файл с расширением jar, а в нём наша модификация, и собственно, можно кидать его в папку mods и пользоваться, но нужно отметить что в этом jar-архиве есть папка META-INF, которая запрещает что-либо из него удалять (Если что .jar можно открывать любым архиватором). Так же следует обратить внимание на то что компилятор автоматически вставит в архив всё, что вы «напрограммировали» и там будут весь код и все ресурсы от модификаций над которыми вы работаете. Если для вас это неприемлемо, просто удалите лишние пути из архива (например platon.mods.megamod, если работаете с mybestmod и т. п.). Так же можно со спокойной совестью удалить META-INF и вообще всё разрахивировать и упаковать в zip-архив, он также будет работать.

Так же немного о build.gradle Вы можете его модифицировать так, чтобы jar-файл автоматически назывался как надо. Откройте его любым текстовым редактором. Вы можете изменить следующие строки, как захотите, например так:

version = "1.0" group= "com.platon.mybestmod" archivesBaseName = "My Best Mod"

Сохраните файл. Таким образом вы получите при компиляции файл My Best Mod-1.0.jar

## Урок 7. Генерация

Теперь мы сделаем так, чтобы теперь какой-либо блок, аналогично рудам, генерировался в обычном мире, в Нижнем мире или в краю. Теперь в главном классе (BaseMyBestMod) после регистрации блока в Forge регистрируем новую переменную:

```
public static BestBlockGenerator bestblockgenerator = new BestBlockGenerator();
```

и исправляем ошибку, создав нужный класс. Естественно, вместо BestBlockGenerator вы можете использовать любое название. Далее в методе `preLoad()`

в любом месте после регистрации блока, который хотите генерировать, добавьте такой код:

```
GameRegistry.registerWorldGenerator(bestblockgenerator, 0);
```

Тем самым вы зарегистрируете ваш генератор. Число «0» обозначает каким по счёту будет загружаться генератор (0 — первым, 1 — вторым и т. д.).

Теперь в созданном классе после `public class BestBlockGenerator`

добавьте `implements IWorldGenerator`

и в тело класса добавьте это:

Скрытый текст |
---|

```
@Override
public void generate(Random rand, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
generateOverworld(rand, chunkX, chunkZ, world);
generateNether(rand, chunkX, chunkZ, world);
generateEnd(rand, chunkX, chunkZ, world);
}
private void generateOverworld(Random rand, int chunkX, int chunkZ, World world) {
generateOverworld(world, rand, chunkX * 16, chunkZ * 16);
}
private void generateNether(Random rand, int chunkX, int chunkZ, World world) {
generateNether(world, rand, chunkX * 16, chunkZ * 16);
}
private void generateEnd(Random rand, int chunkX, int chunkZ, World world) {
generateEnd(world, rand, chunkX * 16, chunkZ * 16);
}
public void generateOverworld(World world, Random rand, int blockXPos, int blockZPos) {
addOreSpawn(BaseMyBestMod.bestblockever, Blocks.stone, world, rand, blockXPos, blockZPos, 16, 16, 1, 2, 1, 1, 10, 5, 6);
}
public void generateNether(World world, Random rand, int blockXPos, int blockZPos) {
addOreSpawn(BaseMyBestMod.bestblockever, Blocks.netherrack, world, rand, blockXPos, blockZPos, 16, 16, 1, 2, 1, 1, 10, 5, 6);
}
public void generateEnd(World world, Random rand, int blockXPos, int blockZPos) {
addOreSpawn(BaseMyBestMod.bestblockever, Blocks.end_stone, world, rand, blockXPos, blockZPos, 16, 16, 1, 2, 1, 1, 10, 5, 6);
}
/**
* Добавляет генерацию руды в Minecraft. Просто воспользуйтесь этим методом для регистрации генерируемых руд.
* @param block Блок, который хотите генерировать
* @param block replace Блок, рядом с которым хотите генерировать
* @param world Мир (не измерение), в котором этот блок должен генерироваться
* @param random Случайное число для получения координат генерации блока
* @param blockXPos Число для того, чтобы было пустое место по координатам X для метода генерации (использует кварцевая руда)
* @param blockZPos Число для того, чтобы было пустое место по координатам Z для метода генерации (использует кварцевая руда)
* @param maxX Число, которое настроит максимальную X координату для генерации руды на оси X на чанк
* @param maxZ Число, которое настроит максимальную Z координату для генерации руды на оси Z на чанк
* @param minVeinSize Минимальное число блоков руды в одной жиле
* @param maxVeinSize Максимальное число блоков руды в одной жиле
* @param minVeinsPerChunk Минимальное число жил в чанке
* @param maxVeinsPerChunk Максимальное число жил в чанке
* @param chancesToSpawn Шанс генерации блоков на чанк в процентах
* @param minY Минимальная координата Y на которой руда может сгенерироваться
* @param maxY Максимальная координата Y на которой руда может сгенерироваться
**/
public static void addOreSpawn(Block ore, Block replace, World world, Random rand, int blockXPos, int blockZPos, int maxX, int maxZ,
int minVeinSize, int maxVeinSize, int minVeinsPerChunk, int maxVeinsPerChunk, int chanceToSpawn, int minY, int maxY) {
if (rand.nextInt(101) < (100 - chanceToSpawn)) return;
int veins = rand.nextInt(maxVeinsPerChunk - minVeinsPerChunk + 1) + minVeinsPerChunk;
for (int i = 0; i < veins; i++) {
int posX = blockXPos + rand.nextInt(maxX);
int posY = minY + rand.nextInt(maxY - minY);
int posZ = blockZPos + rand.nextInt(maxZ);
(new WorldGenMinable(ore, minVeinSize + rand.nextInt(maxVeinSize - minVeinSize + 1),
replace)).generate(world, rand, posX, posY, posZ);
}
}
``` |




Описание параметров метода addOreSpawn() можно увидеть (чтобы разобраться в них), наведя курсор на его название. Эту информацию мы привязали к методу, благодаря javadoc-комментарию[9].

Теперь можно запускать и смотреть результаты.

## Урок 8. Прокси и инстанция

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

```
@Instance("mybestmod")
public static MyBestMod instance;
```

Также, если вы хотите сократить число импортов, то вместо `@Instance`

сделайте `@Mod.Instance`

, от этого ничего не изменится. **Инстанция** — или **экземпляр** — это ссылка на вашу модификацию, которую использует Forge. Если вы не создали её сами, то Forge создаёт её для вас, но в этом случае вы не сможете взаимодействовать с ней, поэтому рекомендовано создать её самому.

Теперь следует сделать прокси. **Прокси** фильтрует контент на то, что должно быть для сервера, а что для клиента. Сервер хранит данные о мире, в то время как клиент рендерит мир. Для создания прокси создайте два класса: ClientProxy для клиента и CommonProxy для сервера. Суперклассом ClientProxy должен быть CommonProxy. Теперь регистрация прокси. Просто добавьте следующий код в главный класс модификации:

```
@SidedProxy(clientSide = "ваш.пакет.ClientProxy", serverSide = "ваш.пакет.CommonProxy")
public static CommonProxy proxy;
```

Прокси и инстанция готовы.

## Урок 9. Моб

Можно приступать к созданию моба. В примере будет создание враждебного моба, со скином игрока. Начните с главного файла модификации. Для удобства регистрации мобов, в примере будет создан отдельный метод:

```
public static void registerEntity(Class entityClass, String name, int primaryColor, int secondaryColor)
{
int entityID = EntityRegistry.findGlobalUniqueEntityId();
long seed = name.hashCode();
EntityRegistry.registerGlobalEntityID(entityClass, name, entityID);
EntityRegistry.registerModEntity(entityClass, name, entityID, instance, 64, 1, true); //эта строка не нужна(зачем она?)
EntityList.entityEggs.put(Integer.valueOf(entityID), new EntityList.EntityEggInfo(entityID, primaryColor, secondaryColor));
}
```

Цвета для яиц призывания вы можете посмотреть здесь, только когда выберете цвет, замените «#» на «0x». Переменная `primaryColor`

назначает цвет фона яйца, а переменная `secondaryColor`

за цвет пупырышек.

Теперь в метод preLoad добавьте следующий код:

```
registerEntity(MyBestEntity.class, "myBestEntity", 0x00FFFF, 0x00008B);
```

Разбор:

Параметр | Описание |
---|---|

MyBestEntity.class | Класс моба. |

«myBestEntity» | ID моба |

0x00FFFF | Цвет фона яйца |

0x00008B | Цвет пупырышек яйца. |


Теперь создайте класс моба и добавьте туда следующий код:

```
public class MyBestEntity extends EntityMob
{
public EntityTest(World par1World)
{
super(par1World);
}
}
```

В примере суперклассом класса моба является класс «EntityMob», предназначенный для враждебных мобов. Также существуют классы «EntityCreature», «EntityAnimal», «EntityLiving» и другие.

Теперь модель, текстура и рендер. В класс CommonProxy добавьте следующий код:

```
public void registerRenderers()
{
// Здесь ничего, так как сервер не рендерит графику или существ!
}
```

Далее в класс ClientProxy добавьте следующий код:

```
@Override
public void registerRenderers()
{
RenderingRegistry.registerEntityRenderingHandler(MyBestEntity.class, new RenderMyBestEntity(new ModelBiped(), 0.5F));
}
```

- Метод
`registerEntityRenderingHandler`

говорит Minecraft, как рендерить существо. `MyBestEntity.class`

— класс моба.`RenderMyBestEntity`

— класс рендера моба, который использует модель`ModelBiped`

.`ModelBiped`

— базовая модель игрока.`0.5F`

— размер тени.

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

```
proxy.registerRenderers();
```

Далее создайте класс RenderВашМоб. В нашем случае это «RenderMyBestEntity». Его суперклассом должен быть класс «RenderBiped». В класс добавьте следующий код:

```
private static final ResourceLocation textureLocation = new ResourceLocation("textures/entity/steve.png");
public RenderTest(ModelBiped model, float shadowSize)
{
super(model, shadowSize);
}
@Override
protected ResourceLocation getEntityTexture(Entity par1Entity)
{
return textureLocation;
}
```

Вместо `textures/entity/steve.png`

поставьте `"IDмодификации:textures/entity/вашМоб.png"`

, то есть в примере будет `"MyBestMod:textures/entity/myBestEntity.png"`

. После этого в папке `assests/idмода/textures`

создайте папку `entity`

и туда скопируйте текстуру моба.

Для локализации яйца моба добавьте в файл локализации следующий код:

```
entity.myBestEntity.name=My Best Entity
```

Теперь зайдите в игру. Во вкладке «Разное» будет яйцо.

Моб закончен.

## Примечания

- ↑ В Java директории указываются не слешами, как в Windows, а точками. То есть «net.minecraft.client» — это когда папка «client» лежит в папке «minecraft», которая лежит в папке «net».
- ↑ Документация Oracle
- ↑ Статья «Java package» на английской Википедии
- ↑ Любое тело в Java обозначается фигурными скобками и обозначает внутренности некоторой подпрограммы. Например,
`public class BaseMyBestMod {`

} указывает, что это класс, а в скобках написано, что он делает. - ↑ В Eclipse встроена функция автоматической организации импортируемых классов (
`Ctrl`+`⇧ Shift`+`O`). - ↑ В Java если строчка написана после двух слешей, то она воспринимается не как код, а как комментарий. Также можно заключить несколько строк в комментарий, закрыв их в конструкцию
`/*Закомментированный текст*/`

- ↑ С помощью
`.setUnlocalizedName("bestpickaxe")`

мы сразу передали методу BestPickAxe информацию, вместо того чтоб в нём писать`this.setUnlocalizedName("bestpickaxe")`

По сути можно все такие аргументы послать через точку. - ↑ Когда вы вводите какой-то путь к методу, переменной и т. п. через точку, после ввода точки вы всегда видите возможные продолжения, пользуйтесь этим, чтобы сократить время написания кода, или если не знаете точно, что вам нужно (ориентируйтесь по тому, что посылается в метод и что он возвращает). Если список исчез, всегда, даже когда нет точки, вы можете посмотреть список доступных продолжений, нажав
`Ctrl`+`Пробел` - ↑ Javadoc-комментарии оставляются над методом, классом, переменной и т. д. для того, чтобы описать назначения класса, метода и т. д. Обособляется конструкцией /**Javadoc-комментарий*/