Создание модификаций с помощью ModLoader

Эту статью нужно срочно переписать!
Вы можете помочь, исправив и дополнив еë.
|




В этой статье будет рассказано о том, как создать модификацию используя ModLoader. Уроки очень просты, рассчитаны на новичка, который никогда не создавал модификации для Minecraft. При этом важно отметить, что ModLoader является безнадежно устаревшим средством загрузки модов, и не актуален для версий выше 1.7.

**Настоятельно рекомендуется проходить учебник последовательно!**

Статус разделов

Название раздела |
Статус
|

Начало Работы | Готов |

Блок | Готов |

Предмет | Готов |

Еда | Моды |

Инструмент | Готов |

Команды для чата | Частично готов |

Генерация объектов | Пишется |

Товар у жителей | Готов |


## Начало работы

### Подготовка

Нужно |
Для последней версии MineCraft
|

MineCraft (чистый) | Скачать |

ModLoader | Скачать |

MineCraft Coder Pack | Архив |

NotePad++ (не обязательно) | Скачать |

JDK 8 | Скачать |


Ролик по моддингу — Подготовка

- Создаём в любом удобном для вас месте пустую папку. Туда распаковываем MineCraft Coder Pack (дальше MCP);
- Кладём папки bin и resources в папку jars, которая находится вместе с распакованным ранее MCP;
- Открываем папку bin и с помощью архиватора открываем файл minecraft.jar. Удаляем папку META-INF и закидываем все файлы ModLoader туда в minecraft.jar;
- Запускаем decompile.bat и ждем, пока консоль не предложит нажать любую клавишу для выхода;
- Все файлы игры будут лежать в появившейся после декомпиляции папке src по пути: \src\minecraft\net\minecraft\src.

### Написание стартового кода

Если вы используете NotePad++, то откройте его, по умолчанию у вас будет открыт файл new 1. Выбираете Файл>Сохранить как… и сохраняете по уже известному пути \src\minecraft\net\minecraft\src (там, где все файлы лежат). (Если у вас нет Notepad++, вы должны сами создать этот файл. В имя файла вписываем mod_***.java.

mod_ — обязательная приставка. *** — любое название (выберите что попроще и без пробелов (пример: mod_block)). И нажимаем сохранить. Пишем в файл:

package net.minecraft.src; import java.util.Random; public class mod_*** extends BaseMod { public void load() { } public String getVersion() { return "1.5.2"; } }

Это базовый шаблон для любой модификации.

package net.minecraft.src;

Эта строчка должна присутствовать в каждом файле в самом верху. Это указание директории вашей модификации(если вы используете ModLoader, то все модификации должны находиться в этой директории).

import java.util.Random;

Эта строчка нужна, когда вы используете расширенные возможности моддинга, о них позже.

public class mod_*** extends BaseMod

Это объявление класса mod_*** (везде меняйте *** на имя вашей модификации).

{ public void load() { } public String getVersion() { return "1.5.2"; } }

Здесь, в public void load() пишутся текстуры для блоков, рецепты, и ещё много чего.

return «1.5.2»; — Версию в кавычках можно менять на любую другую. Обычно используют для обозначения версии Minecraft’а.

### Компиляция и создание готовой модификации

Чтобы проверить код на наличие ошибок необходимо запустить файл recompile.bat. Он заново компилирует игру. Если ошибок нет, то консоль закроется.

После запускаем startclient.bat, после чего запускается игра, где можно опробовать модификацию прямо в игре.

Если вы создали готовую модификацию, и хотите получить готовые рабочие файлы, то

Запускаем reobfuscate.bat, этот скрипт обнаружит все изменённые/добавленные классы и перенесёт их в папку reobf. Теперь в любой MineCraft с установленным ModLoader вы копируете в minecraft.jar эти файлы и модификация устанавливается.
Также, для модификаций **не** изменяющих оригинальные файлы игры их можно запаковать в .zip архив и сбросить в папку «mods».

### Если у вас ошибка при рекомпиляции

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

- Перепроверить все файлы и сравнить их с кодом учебника
- Проверить везде ли и правильно ли вставлены КОДОВЫЕ имена объектов (об этом узнаете ниже)
- Проверить побуквенно всю строчку, на которую ссылается рекомпилятор
- Если не помогает, то копируете код вашей модификации и строку на которую ссылается компилятор и вставляете в обсуждение

### Декомпиляция с модификациями

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

Благо и это сделать тоже можно, и многие наверняка уже догадались как.

Находим нужную модификацию (обязательно на ModLoader), дальше делаем по инструкции выше и, в уже модифицированный minecraft.jar кладем файлы модификации, а после уже запускаем decompile.bat.

Готово! Теперь вы легко сможете изменить чужую модификацию.

## Добавление рецептов

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

public void load() { Рецепты }

, или так:

public void addRecipes() { Рецепты }

### Простой крафт

Рассмотрим такую строчку:

ModLoader.addRecipe(new ItemStack(Block.blockDiamond, 1), new Object[] { "###", "###", "###", '#', Block.dirt });

По элементам:

ModLoader.addRecipe()

— ввод рецепта в код;

new ItemStack(Block.blockDiamond, 1)

— Результат крафта — один алмазный блок;

, new Object[] { "###", "###", "###", '#', Block.dirt }

— Первое «###» обозначает верхнюю строчку верстака, следующие — среднюю и нижнюю. '#', Block.dirt — принятие символа # за блок земли. Можно использовать вместо # любые буквы и многие символы, а пробел заменяет пустую клетку. Результат:

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

Земля |


Если необходимо сделать крафт для сетки 2х2, «###», «###», «###» надо заменить на «##», «##» соответственно. Конечно, крафт выполняется не всегда из одного материала, поэтому следует добавить другие символы. Другой пример:

ModLoader.addRecipe(new ItemStack(Block.bedrock, 1), new Object[] { "ODO", "D D", "ODO", 'O', Block.obsidian, 'D', Block.blockDiamond });

даёт:

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

Алмазный блок + Обсидиан |


// Следует написать готовый вид программы

### Бесформенный крафт

Этот крафт используется, когда нужно случайно расположить предметы в сетке (пример: крафт книги). Код несложный, поэтому разбирайтесь сами:

ModLoader.addShapelessRecipe(new ItemStack(Block.grass, 4), new Object[] { Block.dirt, 1, Item.seeds, 1 });

Вот что даёт этот код:

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

Земля + Семена пшеницы |


### Выплавка

Cледует заметить, что можно выплавить из руды больше одного ресурса за одну выплавку. Образец:

ModLoader.addSmelting(Block.blockGold, new ItemStack(Item.ingotGold, 10), 1.1F);

1.1F — количество опыта, получаемое за переплавку (здесь 1 единица). Результат:

Ингредиенты | Процесс | Результат |
---|---|---|

Золотой блок | Золотой слиток |


## Блок

### Добавление блока

**Сразу хочу сказать, что мы будем создавать блок New Block (так он будет в игре называться). Так будет проще я думаю чем бесконечно ставить ***.**

Для начала после package net.minecraft.src;, сразу после import java.util.Random;, прямо под ней, пишем следующий код

import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map;

Эти строчки могут предотвратить некоторые проблемы при создании блоков.

Далее между

public class mod_*** extends BaseMod {

и

public void load()

мы вставляем строчку, которая создает блок (вещь, предмет)

public static final Block NewBlock = new BlockNewBlock(160, 0).setStepSound(Block.soundStoneFootstep).setBlockName("NewBlock").setHardness(4.5F).setResistance(5F).setLightValue(0.375F);

Разберем данную на первый взгляд непонятную строчку.

public static final Block — Эта строчка собственно и создает блок.

NewBlock — это имя нашего блока, но не в игре! NewBlock мы используем в коде. И использовать это имя нам придется часто.

BlockNewBlock — в процессе создания блока, нам надо будет создать файл специально для этого блока. В данном случае имя этого файла будет BlockNewBlock.java (если вы порылись в src, то наверняка видели файлы BlockDirt, BlockSand и так далее).

(160, 0) — 160 — это ID блока. При создании каждого нового блока (вещи, материала и т. д.) обязательно нужно менять ID. То есть если у нас есть три блока, то ID будут соответственно 160, 161, 162. 0 — дополнительное ID (подробнее здесь).

.setStepSound(Block.soundStoneFootstep) — звук, воспроизводимый при ходьбе по какому-нибудь блоку. Менять нужно soundStoneFootstep на нужные значения. Их можно посмотреть в Block.java (Файл>Открыть>Block.java). Для простоты приведу таблицы всех звуков.

Код |
Звук
|

soundWoodFootstep | Звук при ходьбе по дереву |

soundGravelFootstep | Звук при ходьбе по гравию |

soundGrassFootstep | Звук при ходьбе по траве |

soundStoneFootstep | Звук при ходьбе по камню |

soundMetalFootstep | Звук при ходьбе по драгоценным блокам |

soundGlassFootstep | Звук при ходьбе по стеклу |

soundClothFootstep | Звук при ходьбе по шерсти |

soundSandFootstep | Звук при ходьбе по песку |

soundSnowFootstep | Звук при ходьбе по снегу |

soundLadderFootstep | Звук при движении на лестнице |

soundAnvilFootstep | Звук при движении по наковальне |


.setBlockName(«NewBlock») — тоже самое что и в строчке public static final Block NewBlock. Просто копируем наше кодовое название и вставляем в кавычки.

.setHardness(4.5F) — это время, которое требуется долбить блок, чтобы его добыть. Ориентируетесь на то, что устойчивость земли равна 0.5F.

.setResistance(5F) — это взрывоустойчивость блока. Например у обсидиана (не разрушается TNT) взрывоустойчивость равна 6000F.

.setLightValue(0.375F) — можно убрать этот параметр. Определяет светимость блока. 1F — свет как от светокамня.

В итоге должно получиться так

package net.minecraft.src; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Random; public class mod_NewBlock extends BaseMod { public static final Block NewBlock = new BlockNew(160, 0).setStepSound(Block.soundMetalFootstep).setBlockName("NewBlock").setHardness(0.5F).setResistance(6000F); public void load() { } public String getVersion() { return "1.5.2"; } }

### Имя, текстура, крафт блока

Теперь приступаем к самому главному. К строчке

public void load() { }

Внутри этих скобок мы и запишем путь к текстуре, присвоим имя блоку уже в игре, добавим ему крафт.

Итак для начала создадим нашему блоку имя в игре

ModLoader.addName(NewBlock, "New Block");

Обратите внимание, что в (NewBlock, «New Block») NewBlock — этот как раз наше кодовое имя блока. А в кавычках у нас имя блока в игре. В кавычках действуют знаки форматирования кода. Это означает, что если вы напишите «§ 6NewBlock», то цвет имени вашего блока будет золотым. В таблице указаны свойства, которые мы можем применить к нашему блоку(исключительно визуальные).

Sample | Code | Common Name | Foreground Color | Background Color | ||||||
---|---|---|---|---|---|---|---|---|---|---|

R | G | B | HEX | R | G | B | HEX | |||

§ 0 | Черный | 0 | 0 | 0 | #000000 | 0 | 0 | 0 | #000000 | |

§ 1 | Темно-Синий | 0 | 0 | 170 | #0000AA | 0 | 0 | 42 | #00002A | |

§ 2 | Темно-Зеленый | 0 | 170 | 0 | #00AA00 | 0 | 42 | 0 | #002A00 | |

§ 3 | Темная Вода | 0 | 170 | 170 | #00AAAA | 0 | 42 | 42 | #002A2A | |

§ 4 | Темно-Красный | 170 | 0 | 0 | #AA0000 | 42 | 0 | 0 | #2A0000 | |

§ 5 | Пурпурный | 170 | 0 | 170 | #AA00AA | 42 | 0 | 42 | #2A002A | |

§ 6 | Золотой | 255 | 170 | 0 | #FFAA00 | 42 | 42 | 0 | #2A2A00 | |

§ 7 | Серый | 170 | 170 | 170 | #AAAAAA | 42 | 42 | 42 | #2A2A2A | |

§ 8 | Темно-Серый | 85 | 85 | 85 | #555555 | 21 | 21 | 21 | #151515 | |

§ 9 | Цвет Индиго | 85 | 85 | 255 | #5555FF | 21 | 21 | 63 | #15153F | |

§a | Ярко-Зеленый | 85 | 255 | 85 | #55FF55 | 21 | 63 | 21 | #153F15 | |

§b | Водяной | 85 | 255 | 255 | #55FFFF | 21 | 63 | 63 | #153F3F | |

§c | Красный | 255 | 85 | 85 | #FF5555 | 63 | 21 | 21 | #3F1515 | |

§d | Розовый | 255 | 85 | 255 | #FF55FF | 63 | 21 | 63 | #3F153F | |

§e | Желтый | 255 | 255 | 85 | #FFFF55 | 63 | 63 | 21 | #3F3F15 | |

§f | Белый | 255 | 255 | 255 | #FFFFFF | 63 | 63 | 63 | #3F3F3F |


Код | Описание |
---|---|

§l | Выделение
|

§m | |

§n | Подчеркнутое
|

§o | Наклонный
|


Далее зададим путь к текстуре

NewBlock.blockIndexInTexture = ModLoader.addOverride("/terrain.png", "/textures/New Block.png");

Итак «/textures/New Block.png». /textures это папка в minecraft.jar, которая, как вы помните находится в jars. Можно изменить на любое. /New Block.png это картинка 16x16, положенная в эту папку. Имя и формат должны В ТОЧНОСТИ совпадать с указанными в коде.

То есть, написав эту строчку, идем в jars, bin, открываем minecraft.jar WinRar и вставляем в папку textures (или то, что вы указали) эту картинку .png.

Регистрируем блок:

ModLoader.registerBlock(NewBlock);

И, наконец, наше любимое — рецепт:

ModLoader.addRecipe(new ItemStack(NewBlock, 1), new Object[] { "$@$", "@$@", "$@$", '$', Block.glass, '@', Block.sandStone, 0 });

Вот пример готового кода:

package net.minecraft.src; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Random; public class mod_NewBlock extends BaseMod { public static final Block NewBlock = new BlockNew(160, 0).setStepSound(Block.soundMetalFootstep).setBlockName("NewBlock").setHardness(0.5F).setResistance(6000F); //Для майнкрафт 1.5.2 заменить .setBlockName() на .setUnlocalizedName(); public void load() { NewBlock.blockIndexInTexture = ModLoader.addOverride("/terrain.png", "/textures/New Block.png"); ModLoader.registerBlock(NewBlock); ModLoader.addName(NewBlock, "New Block"); ModLoader.addRecipe(new ItemStack(NewBlock, 1), new Object[] { "#@#", "#@#", "#@#", '#', Block.dirt, '@', Block.glass }); } public String getVersion() { return "1.5.2"; } }

### Создание файла блока

Создаем новый файл BlockNewBlock.java в той же директории src\minecraft\net\minecraft\src. Пишем в него:

package net.minecraft.src; import java.util.Random; public class BlockNewBlock extends Block { public BlockNewBlock(int par1, int par2) { super(par1, par2, Material.rock); //для версии майнкрафт 1.5.2 убрать par2 this.setCreativeTab(CreativeTabs.tabBlock); } public int quantityDropped(int par1) { return 1; } }

return mod_***.NewBlock.shiftedIndex — Что будет выпадать из блока при разрушении.

return 1 — Количество выпадающего блока или предмета.

Обращаю ваше внимание на строчку

(CreativeTabs.tabBlock);

: Эта сточка помещает наш блок в меню творческого режима в игре. Как вы помните, там несколько вкладок — Материалы, Блоки и т. д. Так вот .tabBlock добавляет наш блок в закладку Блоки. Вот таблица значений, которые можно использовать вместо

.tabBlock

:

Код |
Вкладка Creative
|

tabBlock | Добавляет объект во вкладку «Блок» |

tabDecorations | Добавляет объект во вкладку «Декоративные» |

tabRedstone | Добавляет объект во вкладку «Механизмы» |

tabTransport | Добавляет объект во вкладку «Транспортировка» |

tabMisc | Добавляет объект во вкладку «Разное» |

tabFood | Добавляет объект во вкладку «Еда» |

tabTools | Добавляет объект во вкладку «Инструменты» |

tabCombat | Добавляет объект во вкладку «Оружие» |

tabBrewing | Добавляет объект во вкладку «Зельеварение» |

tabMaterials | Добавляет объект во вкладку «Материалы» |


### Генерация блока

Этот раздел нужен для тех, кто хочет, чтобы их блок генерировался в мире (или в аду). Например при создании руды.

Генерация в обычном мире.

Итак сразу под строчкой

public class mod_NewBlock extends BaseMod {

пишем

public void generateSurface(World world, Random random, int i, int j) { for(int k = 0; k < 5; k++) { int randPosX = i + random.nextInt(16); int randPosY = random.nextInt(128); int randPosZ = j + random.nextInt(16); (new WorldGenMinable(yourOreBlockName.blockID, 17)).generate(world, random, randPosX, randPosY, randPosZ); } }

Разбираем:

for(int k = 0; k < 5; k++) — k < 5 чем больше цифра после <, тем чаще генерируется блок.

int randPosY = random.nextInt(128); — 128 высота блока. У алмазной руды 16. То есть алмазная руда генерируется на 16 блоков от коренной породы

(yourOreBlockName.blockID, 17)) — yourOreBlockName.blockID имя вашего блока (BlockNew.blockID).

Рекомпилируем и ищем наш блок.

Генерация в аду.

Заменяем код, написанный выше на

public void generateNether(World world, Random rand, int i, int j) { for(int m = 0; m < 7; m++) { int randPosX = i + rand.nextInt(16); int randPosY = rand.nextInt(128); int randPosZ = j + rand.nextInt(16); (new NetherGenMinable(yourNetherOre.blockID, 15)).generate(world, rand, randPosX, randPosY, randPosZ); } }

Все параметры одинаковы как и с генерацией в обычном мире.

Создаем файл NetherGenMinable.java и вписываем в него (без изменений, код уже готов)

package net.minecraft.src; import java.util.Random; public class NetherGenMinable extends WorldGenerator { /** The block ID of the ore to be placed using this generator. */ private int minableBlockId; /** The number of blocks to generate. */ private int numberOfBlocks; public NetherGenMinable(int par1, int par2) { this.minableBlockId = par1; this.numberOfBlocks = par2; } public boolean generate(World par1World, Random par2Random, int par3, int par4, int par5) { float var6 = par2Random.nextFloat() * (float)Math.PI; double var7 = (double)((float)(par3 + 8) + MathHelper.sin(var6) * (float)this.numberOfBlocks / 8.0F); double var9 = (double)((float)(par3 + 8) - MathHelper.sin(var6) * (float)this.numberOfBlocks / 8.0F); double var11 = (double)((float)(par5 + 8) + MathHelper.cos(var6) * (float)this.numberOfBlocks / 8.0F); double var13 = (double)((float)(par5 + 8) - MathHelper.cos(var6) * (float)this.numberOfBlocks / 8.0F); double var15 = (double)(par4 + par2Random.nextInt(3) - 2); double var17 = (double)(par4 + par2Random.nextInt(3) - 2); for (int var19 = 0; var19 <= this.numberOfBlocks; ++var19) { double var20 = var7 + (var9 - var7) * (double)var19 / (double)this.numberOfBlocks; double var22 = var15 + (var17 - var15) * (double)var19 / (double)this.numberOfBlocks; double var24 = var11 + (var13 - var11) * (double)var19 / (double)this.numberOfBlocks; double var26 = par2Random.nextDouble() * (double)this.numberOfBlocks / 16.0D; double var28 = (double)(MathHelper.sin((float)var19 * (float)Math.PI / (float)this.numberOfBlocks) + 1.0F) * var26 + 1.0D; double var30 = (double)(MathHelper.sin((float)var19 * (float)Math.PI / (float)this.numberOfBlocks) + 1.0F) * var26 + 1.0D; int var32 = MathHelper.floor_double(var20 - var28 / 2.0D); int var33 = MathHelper.floor_double(var22 - var30 / 2.0D); int var34 = MathHelper.floor_double(var24 - var28 / 2.0D); int var35 = MathHelper.floor_double(var20 + var28 / 2.0D); int var36 = MathHelper.floor_double(var22 + var30 / 2.0D); int var37 = MathHelper.floor_double(var24 + var28 / 2.0D); for (int var38 = var32; var38 <= var35; ++var38) { double var39 = ((double)var38 + 0.5D - var20) / (var28 / 2.0D); if (var39 * var39 < 1.0D) { for (int var41 = var33; var41 <= var36; ++var41) { double var42 = ((double)var41 + 0.5D - var22) / (var30 / 2.0D); if (var39 * var39 + var42 * var42 < 1.0D) { for (int var44 = var34; var44 <= var37; ++var44) { double var45 = ((double)var44 + 0.5D - var24) / (var28 / 2.0D); if (var39 * var39 + var42 * var42 + var45 * var45 < 1.0D && par1World.getBlockId(var38, var41, var44) == Block.netherrack.blockID) { par1World.setBlock(var38, var41, var44, this.minableBlockId); } } } } } } } return true; } }

Все готово, можете искать вашу руду в аду.

### Мульти-текстура

Чтобы у нашего блока были разные текстуры с разных сторон, надо немного изменить код.

package net.minecraft.src; public class mod_Block extends BaseMod { public static final Block Multi= new BlockMulti(160, 0).setBlockName("Multi").setHardness(3F).setResistance(4F).setLightValue(1F); public static int MultiHereBottom = ModLoader.addOverride("/terrain.png", "/textures/blockbottom.png"); public static int MultiHereTop = ModLoader.addOverride("/terrain.png", "/textures/blocktop.png"); public static int MultiHereSides = ModLoader.addOverride("/terrain.png", "/textures/blocksides.png"); public void load() { Multi.blockIndexInTexture = ModLoader.addOverride("/terrain.png", "/textures/image.png"); ModLoader.registerBlock(Multi); ModLoader.addName(Multi, "Multi Block"); ModLoader.addRecipe(new ItemStack(Multi, 1), new Object [] {"#", Character.valueOf('#'), Block.dirt}); } public String getVersion() { return "1.4.7"; } }

public static final Block Multi= new BlockMulti(160, 0).setBlockName("Multi").setHardness(3F).setResistance(4F).setLightValue(1F);

— все также как и с обычным блоком.

public static int MultiHereBottom = ModLoader.addOverride("/terrain.png", "/textures/blockbottom.png");

— тут текстура на нижнюю сторону блока

public static int MultiHereTop = ModLoader.addOverride("/terrain.png", "/textures/blocktop.png");

— на верхнюю

public static int MultiHereSides = ModLoader.addOverride("/terrain.png", "/textures/blocksides.png")

; — и боковые стороны

Далее все как и с обычным блоком. Загружаем картинки, рекомпилируем и радуемся мульти-текстурным блоком.

### Падающий блок

В mod_*** все также, а в BlockNewBlock.java вставляем

package net.minecraft.src; import java.util.Random; public class BlockTest extends BlockSand { public static boolean fallInstantly = false; public BlockTest(int par1) { super(par1, Block.stone.blockIndexInTexture, Material.rock); this.setCreativeTab(CreativeTabs.tabBlock); } }

extends BlockSand — этот параметр и заставляет наш блок падать, так как копирует гравитационные свойства у песка.

Блок готов. Можно рекомпилировать и проверять в игре (см. 1.1 Компиляция и создание готового мода).

### Блок, наносящий урон

Работать мы будем исключительно в BlockNewBlock.java.

После

public int quantityDropped(int par1) { return (1); }

Пишем

public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) { par5Entity.attackEntityFrom(DamageSource.cactus, 1); }

onEntityCollidedWithBlock — условие, при котором игрок находится вплотную к блоку

par5Entity.attackEntityFrom(DamageSource.cactus, 1); — урон типа cactus (кактус) в полсердца (цифра 1).

Теперь, когда вы подойдете к блоку вам будет наносится урон в 1 полсердце.

### Блок, испускающий частицы

В файле блока вставляем эту строчку

public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) { super.randomDisplayTick(par1World, par2, par3, par4, par5Random); if (par5Random.nextInt(10) == 0) { par1World.spawnParticle("reddust", (double)((float)par2 + par5Random.nextFloat()), (double)((float)par3 + 1.1F), (double)((float)par4 + par5Random.nextFloat()), 0.0D, 0.0D, 0.0D); } }

Этот код заставляет наш блок испускать частицы, как блок красного камня.

par1World.spawnParticle(«reddust» — reddust — собственно тип частиц.

Вот так будет выглядеть код появления частиц вокруг блока грязи

package net.minecraft.src; public class BlockDirt extends Block { protected BlockDirt(int par1, int par2) { super(par1, par2, Material.ground); this.setCreativeTab(CreativeTabs.tabBlock); } public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) { super.randomDisplayTick(par1World, par2, par3, par4, par5Random); if (par5Random.nextInt(20) == 0) { par1World.spawnParticle("reddust", (double)((float)par2 + par5Random.nextFloat()), (double)((float)par3 + 1.1F), (double)((float)par4 + par5Random.nextFloat()), 0.0D, 0.0D, 0.0D); } } }

Таблица кодов частиц:

Вид частиц | Код |
---|---|

Дым | «smoke» |

Частицы разрушения блока (имя блока после _). | «iconcrack_» |

Частицы разбитого яйца | «snowballpoof» |

Частицы разрушения инструмента (имя инструмента после _) | «tilecrack_» |

Частицы портала | «portal» |

Частицы, появляющиеся под водой | «splash» |

Пузырьки воды | «bubble» |

Споры мицелия | «townaura» |

Анимация взрыва | «hugeexplosion» |

Огонь | «flame» |

Частицы в виде сердечек | «heart» |

Критический урон | «crit» |

Магический критический урон | «magicCrit» |

Ноты | «note» |

Частицы магических рун | «enchantmenttable» |

Частицы лавы | «lava» |

Частицы следов во время ходьбы | «footstep» |

Редстоун частицы | «reddust» |

Капли воды | «dripWater» |

Капли лавы | «dripLava» |

Куски слизня | «slime» |


## Предмет

### Добавление предмета

**Как и в разделе «Блок», для удобства мы будем создавать предмет NewItem.**

Долго разбираться в коде не будем, так как все разобрано в разделе «Блок».

Итак, как и с блоком, между public class mod_*** extends BaseMod { и void load мы вставляем строчку, которая создает блок (вещь, предмет)

public static final Item NewItem = new ItemNewItem(5000).setItemName("NewItem");

Тут все параметры абсолютно совпадают с параметрами создания блока:

public static final Block NewBlock = new BlockNewBlock(160, 0).setStepSound(Block.soundStoneFootstep).setBlockName("NewBlock").setHardness(4.5F).setResistance(5F).setLightValue(0.375F);

final Item — создание предмета, final Block — создания блока.

NewItem = new ItemNewItem(5000) и NewBlock = new BlockNewBlock(160, 0) — тут все также. ID у предмета 5000. Не забываем с каждым предметом увеличивать ID.

Далее у блока идут функции и сходство только в .setItemName(«NewItem»).

Как видите код создания блока и предмета почти одинаковы.

Вот как должен выглядеть код

package net.minecraft.src; import java.util.Random; public class mod_NewItem extends BaseMod { public static final Item NewItem = new ItemNewItem(5000).setItemName("NewItem"); public void load() { } public String getVersion() { return "1.4.7"; } }

### Имя, текстура, крафт предмета

Тут смотрите подраздел «Имя, текстура, крафт блока» в разделе «Блок». Всё в точности так же, только NewBlock заменяем на NewItem.

Вот так в конечном итоге выглядит код:

package net.minecraft.src; import java.util.Random; public class mod_NewItem extends BaseMod { public static final Item NewItem = new ItemNewItem(5000).setItemName("NewItem"); public void load() { NewItem.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewItem.png"); ModLoader.addName(NewItem, "New Item"); ModLoader.addRecipe(new ItemStack(NewItem, 1), new Object [] {"###", "###", "###", Character.valueOf('#'), Block.dirt}); } public String getVersion() { return "1.4.7"; } }

Единственное отличие: не нужно добавлять ModLoader.registerBlock(NewBlock);.

### Создание файла предмета

Создаем новый файл ItemNewItem.java. Вспомните new ItemNewItem(5000) в строке добавления мода — ItemNewItem и определяет название нашего нового файла.

package net.minecraft.src; import java.util.Random; public class ItemNewItem extends Item { public ItemNewItem (int i) { super(i); maxStackSize = 64; this.setCreativeTab(CreativeTabs.tabMaterials); } }

*maxStackSize = 64* — Количество предметов в одном слоте.

this.setCreativeTab(CreativeTabs.tabMaterials); — добавление во вкладку в креативе. Смотрите «Создание файла блока».

Предмет готов. Запускаем recompile, затем startclient и проверяем. Если есть ошибки, то ещё раз читаем статью.

## Еда

### Создание еды

Ролик по моддингу — создание еды

Создать еду очень просто: надо заменить код определения предмета

public static final Item NewItem = new ItemNewItem(5000).setItemName("NewItem");

на

public static final Item MyFood = new ItemMyFood(5000, 6, 1F, true).setItemName("MyFood");

6, 1F, true — 6 — сколько восстанавливает еда восстанавливает половинок очков голода (соответственно число 20 полностью восстанавливает голод), 1F — время до момента, когда персонаж снова начнет голодать, true — false — можно/нельзя приручить едой волка.

## Инструмент

### Создание инструмента

Ролик по моддингу — Инструмент

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

public static final Item NewSword = (new ItemSword(203, EnumToolMaterial.EMERALD)).setItemName("NewSword");

yourSword — кодовое имя.

(new ItemSword — созданием меча.

203, EnumToolMaterial.EMERALD — тут ID и очень важная вещица, о которой позже.

.setItemName(«yourSword») — снова кодовое имя.

Теперь подробнее о EnumToolMaterial.***. *** — это материал нашего инструмента. Переходим в EnumToolMaterial.java и видим различные материалы нашего инструмента. Приведу табличку материалов.

Код |
Материал
|

WOOD | Дерево |

STONE | Камень |

IRON | Железо |

GOLD | Золото |

EMERALD | Изумруд |

DIAMOND | Алмаз |


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

Теперь разберем эти странные цифры: 3, 1561, 8.0F, 3, 10 (в пример я взял EMERALD). 3 — уровень разрушения блоков, насколько серьёзные блоки можно добыть. 1561 — количество использований. 8.0F — скорость разрушения блоков. 3 — урон мобам. 10 — шанс на хорошее зачаровывание.

В этом примере мы создали меч. Следующие строки создают мотыгу, лопату, кирку, топор соответственно.

public static final Item NewHoe = new ItemHoe(204, EnumToolMaterial.MATERIALNAME).setItemName("NewHoe"); public static final Item NewShovel = new ItemSpade(202, EnumToolMaterial.MATERIALNAME.setItemName("NewShovel"); public static final Item NewPickaxe = new ItemPickaxe(200, EnumToolMaterial.MATERIALNAME).setItemName("NewPickaxe"); public static final Item NewAxe = new ItemAxe(201, EnumToolMaterial.MATERIALNAME).setItemName("NewAxe");

MATERIALNAME заменяете на нужный или созданный вами.

### Имя, текстура, крафт инструмента

Вот код для всего tool сета. Пишем в public void {

public void load() { NewPickaxe.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewPickaxe.png"); NewAxe.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewAxe.png"); NewShovel.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewShovel.png"); NewSword.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewSword.png"); NewHoe.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewHoe.png"); ModLoader.addRecipe(new ItemStack(NewPickaxe, 1), new Object [] {"###", " X ", " X ", '#', Block.dirt, 'X', Item.stick}); ModLoader.addRecipe(new ItemStack(NewShovel, 1), new Object [] {"#", "X", "X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewSword, 1), new Object [] {"#", "#", "X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewAxe, 1), new Object [] {"##", "#X ", " X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewHoe, 1), new Object [] {"##", " X", " X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addName(NewPickaxe, "Pickaxe Name"); ModLoader.addName(NewAxe, "Axe Pickaxe Name"); ModLoader.addName(NewShovel, "Shovel Pickaxe Name"); ModLoader.addName(NewSword, "Sword Pickaxe Name"); ModLoader.addName(NewHoe, "Hoe Pickaxe Name"); } public String getVersion() { return "1.4.7"; } }

Вот собственно и все (не забудьте добавить текстуры).

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

package net.minecraft.src; public class mod_NewMod extends BaseMod { public static final Item NewPickaxe = (new ItemPickaxe(200, EnumToolMaterial.MATERIALNAME)).setItemName("NewPickaxe"); public static final Item NewAxe = (new ItemAxe(201, EnumToolMaterial.MATERIALNAME)).setItemName("NewAxe"); public static final Item NewShovel = (new ItemSpade(202, EnumToolMaterial.MATERIALNAME)).setItemName("NewShovel"); public static final Item NewSword = (new ItemSword(203, EnumToolMaterial.MATERIALNAME)).setItemName("NewSword"); public static final Item NewHoe = (new ItemHoe(204, EnumToolMaterial.MATERIALNAME)).setItemName("NewHoe"); public void load() { NewPickaxe.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewPickaxe.png"); NewAxe.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewAxe.png"); NewShovel.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewShovel.png"); NewSword.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewSword.png"); NewHoe.iconIndex = ModLoader.addOverride("/gui/items.png", "/textures/NewHoe.png"); ModLoader.addRecipe(new ItemStack(NewPickaxe, 1), new Object [] {"###", " X ", " X ", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewShovel, 1), new Object [] {"#", "X", "X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewSword, 1), new Object [] {"#", "#", "X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewAxe, 1), new Object [] {"##", "#X ", " X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addRecipe(new ItemStack(NewHoe, 1), new Object [] {"##", " X", " X", '#', Block.dirt, Character.valueOf('X'), Item.stick}); ModLoader.addName(NewPickaxe, "Pickaxe Name"); ModLoader.addName(NewAxe, "Axe Pickaxe Name"); ModLoader.addName(NewShovel, "Shovel Pickaxe Name"); ModLoader.addName(NewSword, "Sword Pickaxe Name"); ModLoader.addName(NewHoe, "Hoe Pickaxe Name"); } public String getVersion() { return "1.4.7"; } }

## Товар у жителей

Если вы хотите, чтобы ваши предметы|блоки продавались у жителей, то в mod_*** пишем

package net.minecraft.src; public class mod_*** extends BaseMod { TradeEntry test = new TradeEntry(Item.gunpowder.itemID, 0.5f, false, 2, 4); public String getVersion() { return "1.4.7"; } public void load() { ModLoader.addTrade(1, test); } }

TradeEntry test = new TradeEntry(Item.gunpowder.itemID, 0.5f, false, 2, 4); — Item.gunpowder.itemID — тут ваш предмет, блок и т. д.

0.5f — шанс появления в продаже у жителей

ModLoader.addTrade(1, test); — 1 — профессия жителя

Цифры 2, 4 — это курс валюты для продажи, то есть, товар будет продаваться от 2 до 4 изумрудов.

False — это значит что житель продает товар вам, соответственно true — это значит что товар продаете вы.

Код профессии |
Название профессии жителя |
Цвет одежды
|

0 | Фермер | Коричневый |

1 | Библиотекарь | Белый |

2 | Священник | Фиолетовый |

3 | Кузнец | Черный |

4 | Мясник | Белый |


## Генерация объектов

Ролик по моддингу — Генерация объектов

## Команды для чата

### Изменение существующих команд

Названия всех команд в игре (и сервера) начинается с Command.

Например открыв файл CommandKill.java мы увидим такой код

package net.minecraft.src; public class CommandKill extends CommandBase { public String getCommandName() { return "kill"; } /** * Return the required permission level for this command. */ public int getRequiredPermissionLevel() { return 0; } public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) { EntityPlayerMP var3 = getCommandSenderAsPlayer(par1ICommandSender); var3.attackEntityFrom(DamageSource.outOfWorld, 1000); par1ICommandSender.sendChatToPlayer("Ouch. That looks like it hurt."); } }

Тут все просто:

return «kill»; — kill — это строка после /. Можем изменить её например для краткости на k. В таком случае при вводе в игре /kill нам сообщат, что такой команды не существует, а при вводе /k команда выполнится.

public int getRequiredPermissionLevel() — пока что не разобрался (предположительно уровень доступа, то есть, например 0, значит, могут использовать обычные игроки, а 2 — только админы.

var3.attackEntityFrom(DamageSource.outOfWorld, 1000); — эффект от команды — урон в 1000 единиц вида outOfWorld (падение в пустоту).

par1ICommandSender.sendChatToPlayer(«Ouch. That looks like it hurt.»); — в кавычках сообщение при смерти в чат.

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

В mod_***, как уже для многих стало привычно, пишем под public class mod_test extends BaseMod {

public static final ICommand NewCommand = new CommandNewCommand();

NewCommand — кодовое название команды.

CommandNewCommand — название .java файла команды.

В public void load() { пишем

ModLoader.addCommand(spawn);

Просто указываем вместо NewCommand кодовое имя вашей команды. я Создаем файл CommandNewCommand.java. Пока ещё не разобраны кодировки, здесь приведён код спауна крипера.

package net.minecraft.src; public class CommandNewCommand extends CommandBase { public String getCommandName() { return "spawn"; } public int func_82362_a() { return 0; } public void processCommand(ICommandSender par1ICommandSender, String[] par2ArrayOfStr) { EntityPlayerMP var3 = getCommandSenderAsPlayer(par1ICommandSender); World obj = var3.worldObj; Entity a = EntityList.createEntityByID(Integer.parseInt(par2ArrayOfStr[0]), obj); a.setPosition(Integer.parseInt(par2ArrayOfStr[1]), Integer.parseInt(par2ArrayOfStr[2]), Integer.parseInt(par2ArrayOfStr[3])); obj.spawnEntityInWorld(a); } }