Minecraft Wiki
(Отмена правки 263962, сделанной участником 92.126.91.39) Абсолютно бесполезное дополнение туториала. До такого глупо самому не додуматься.)
Строка 72: Строка 72:
 
Также можно установить будет ли блок светиться. Больше число - светлее (до 15).
 
Также можно установить будет ли блок светиться. Больше число - светлее (до 15).
 
this.setLightLevel(0F);
 
this.setLightLevel(0F);
 
Ещё можно установить звук ходьбы по блоку, и звук когда вы ставите и ломаете блок.
 
this.setStepSound(soundMetalFootstep);
 
 
Звуки:
 
 
soundAnvilFootstep – ходьба по наковальне,
 
soundClothFootstep – ходьба по шерсти,
 
soundGlassFootstep – ходьба по стеклу,
 
soundGrassFootstep – ходьба по траве,
 
soundGravelFootstep – ходьба по гравию,
 
soundLadderFootstep – ходьба по лестнице,
 
soundMetalFootstep – ходьба по драгоценным блокам,
 
soundPowderFootstep – ходьба по пыли,
 
soundSandFootstep – ходьба по песку,
 
soundSnowFootstep – ходьба по снегу,
 
soundStoneFootstep – ходьба по камню,
 
soundWoodFootstep – ходьба по дереву.
 
   
 
Теперь давайте добавим текстуру блоку. Она должна быть любой, но 16x16 пикселей. Например можно создать картинку, написать в ней "Б" и уменьшить до 16*16 пикселей и чуть-чуть подредактировать. Можете скачать мою. [[Файл:Пример текстуры(Туториал Forge).png]] Желательно, чтоб название было как у блока, а расширение обязательно .png
 
Теперь давайте добавим текстуру блоку. Она должна быть любой, но 16x16 пикселей. Например можно создать картинку, написать в ней "Б" и уменьшить до 16*16 пикселей и чуть-чуть подредактировать. Можете скачать мою. [[Файл:Пример текстуры(Туториал Forge).png]] Желательно, чтоб название было как у блока, а расширение обязательно .png

Версия от 15:08, 12 июля 2014

Здесь находятся инструкции по созданию модификаций, работающие для версии 1.7+


Подготовка среды и настройка

Сначала подготовим среду для работы с кодом Minecraft.

Forge

Собственно, для создания модов нам нужен Forge, а значит нужно его скачать. Здесь последние сборки Forge. Вам нужна последняя сборка для 1.7.2 Так что выберите последнюю сборку на 1.7.2 и напротив неё нажмите src (или на звездочку - быстрее). Теперь создайте любую папку там, где вам удобно (например, у меня это D:\MCModding), в ней будет находиться Forge и ваш мод. В эту папку распакуйте содержимое архива с Forge.

Теперь нам нужно установить Forge, чтобы при этом тут оказался декомпилированный Майнкрафт. Для этого можно создать в этой папке .bat-файл с содержимым gradlew.bat SetupDevWorkspace и запустить его, а после завершения изменить содержимое на gradlew.bat eclipse и снова запустить. Также вместо всего этого можно запустить командную строку в этой папке (например, нажать ⇧ Shift + ПКМ по этой папке и выбрать "Открыть окно команд") и выполнить поочередно команды gradlew.bat SetupDevWorkspace и gradlew.bat eclipse соответственно.

Установка готова.

Настройка Eclipse

Нам нужно настроить Eclipse для работы с Minecraft. Первым делом зайдите в него. Он предложит выбрать рабочую директорию (Workspace). Введите туда путь к папке eclipse в папке с mcp и поставьте галочку для того чтоб окно больше не появлялось. Например у меня папка D:\MCModding\eclipse. Если всё прошло успешно, то слева в Eclipse вы увидите раскрывающееся меню Minecraft а снизу не увидите красных ошибок.


Поздравляю! Вы успешно настроили среду для того чтоб начать писать моды.

Основные уроки

Урок 1. Директория

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

Заранее придумайте название своего мода (например, MyBestMod). Перейдём к тому, где должен быть мод в структуре классов Minecraft. Существует некоторый этикет, как оформлять код и всё, что с ним связано. Раскройте проект Minecraft, далее src/main/java. В src/main/java лежит всё, что относится к коду Minecraft. Как вы видите, там есть подпапки (или пакеты) типа cpw.mods.fml[1] и т.д. Разработчик мода (fml — Forge Mod Loader), которого зовут cpw, решил оформить структуру расположения именно так. То есть, если ваш никнейм, например, platon, а название вашего мода — My Best Mod, то нажмите на src ПКМ и выберите New -> package. В поле Name наберите "platon.mods.mybestmod" с учётом регистра. Это создаст директорию, в которой вы и будете работать с модом. Всё, далее можете приступать непосредственно к его созданию.

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

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

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

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

@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 знает или догадывается, где их искать[3].

Вот и всё. Основа мода готова. Можете запустить 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 в котором написано что такое блок. И не хватает аргументов которые нужно дать тому классу, чтобы ваш блок был особенным. материал, прочность и т.д. Поэтому просто исправьте ошибку первым способом, он сам её исправит. дописав немного. Строчку с двумя слешами можно стереть[4]. В скобочках у объекта, где написаны аргументы, которые должны быть посланы снаружи уберите аргумент 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);

Устанавливает, что можно сломать блок киркой алмазного уровня, не ниже.

Также можно установить будет ли блок светиться. Больше число - светлее (до 15).

this.setLightLevel(0F);

Теперь давайте добавим текстуру блоку. Она должна быть любой, но 16x16 пикселей. Например можно создать картинку, написать в ней "Б" и уменьшить до 16*16 пикселей и чуть-чуть подредактировать. Можете скачать мою. Пример текстуры(Туториал Forge) Желательно, чтоб название было как у блока, а расширение обязательно .png

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

this.setBlockTextureName("mybestmod:BlockBestBlockEver");

Давайте немного разберемся насчёт "mybestmod:BlockBestBlockEver". Должно быть написано "краткое название мода:название файла", но название без .png

Теперь поместим текстуру в проект. Слева в окне директорий проекта выберите src/main/resources и нажмите правой кнопкой и создайте директорию.(New -> package) Назовите так: assets.краткое название мода.textures.blocks (assets.mybestmod.textures.blocks). Теперь мышкой перетяните текстуру из windows в эту директорию. В окне выберите Copy files.

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

GameRegistry.registerBlock(bestblockever, "bestblockever");

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

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

Ну вот и всё, блок создан. И теперь самый волнующий момент. Запускайте 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");

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

Немного об ItemPickaxe: думаю, должно быть понятно, что pickaxe - это кирка по-английски. И, соответственно, extends ItemPickaxe говорит о том, что мы "продолжаем" или дополняем класс ItemPickaxe, в котором указаны все базовые характеристики и функции, такого Item'а или предмета, как кирка. Таким образом можно продолжать любой класс, в зависимости от того, какой предмет нужен. То есть, если нужна еда, то мы продолжаем класс ItemFood, если броня, то ItemArmor, а если свой особенный предмет, то просто Item. Не забывайте: вы всегда можете посмотреть список возможных продолжений того, что вы пишете.[6]

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

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

Тогда ошибка исчезнет. Строка super(EnumToolMaterial.EMERALD); говорит о том, что пошлёт в супер-класс информацию о том, что кирка обладает свойствами алмазной кирки. Ну и также допишем после этой строчки

this.setCreativeTab(CreativeTabs.tabTools);

тем самым добавив кирку в раздел инструменты в Creative.

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

this.setTextureName("mybestmod:BestPickAxe");

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

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

Урок 5. Крафт

Собственно, у нас есть блок и предмет. Мы можем их держать в руках, а блок даже ставить. Но а если мы хотим достать их, играя в режиме Выживания? Тогда блок или предмет можно только найти или скрафтить. Добавить крафт очень просто, поэтому урок короткий. Например я хочу скрафтить блок, положив во все верхние и нижние клетки железные слитки, в оставшиеся боковые - гравий, а в середину - обсидиан, тогда я запишу вот это в тело метода 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 блока Земли, покрытой травой.

Так же в майнкрафте, как мы знаем, присутствует переплавка одних предметов/блоков в другие. Рецепт такой переплавки создаётся всего одной строкой, которую нужно писать после регистрации блока 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, а в нём наш мод, и собственно, можно кидать его в папку mods и пользоваться, но нужно отметить что в этом jar-архиве есть папка META-INF, которая запрещает что-либо из него удалять (Если что .jar можно открывать любым архиватором). Так же следует обратить внимание на то что компилятор автоматически вставит в архив всё, что вы "напрограммировали" и там будут весь код и все ресурсы от модов над которыми вы работаете. Если для вас это неприемлемо, просто удалите лишние пути из архива (например platon.mods.megamod, если работаете с mybestmod и т.п.). Так же можно со спокойной совестью удалить META-INF и вообще всё разрахивировать и упаковать в zip-архив, он также будет работать.

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

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

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

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

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

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 random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator,
		IChunkProvider chunkProvider)
	{
		switch(world.provider.dimensionId)
		{
			case -1: generateNether(world, random, chunkX * 16, chunkZ * 16);
			case 0: generateOverworld(world, random, chunkX * 16, chunkZ * 16);
			case 1: generateEnd(world, random, chunkX * 16, chunkZ * 16);
		}
	}

	private void generateEnd(World world, Random random, int x, int z) 
	{
    	int Xcoord = x + random.nextInt(16);
    	int Ycoord = 10 + random.nextInt(128);
    	int Zcoord = z + random.nextInt(16);
    	
    	(new WorldGenMinable(BaseMyBestMod.bestblockever, 1, 15, Blocks.end_stone)).generate(world, random, Xcoord, Ycoord, Zcoord);
	}

	private void generateOverworld(World world, Random random, int x, int z) 
	{
		this.addOreSpawn(BaseMyBestMod.bestblockever, world, random, x, z, 16, 16, 4 + random.nextInt(3), 10, 15, 50);
	}

	private void generateNether(World world, Random random, int x, int z)
	{
        int Xcoord = x + random.nextInt(16);

        int Ycoord = 10 + random.nextInt(128);

        int Zcoord = z + random.nextInt(16);

        (new WorldGenMinable(BaseMyBestMod.bestblockever, 1, 15, Blocks.netherrack)).generate(world, random, Xcoord, Ycoord, Zcoord);
	}
	
    /**
     * Добавляет генерацию руды в Minecraft. Просто воспользуйтесь этим методом для регистрации генерируемых руд.

     * @param Блок, который хотите генерировать

     * @param Мир (не измерение), в котором этот блок должен генерироваться

     * @param Случайное число для получения координат генерации блока

     * @param Число для того, чтобы было пустое место по координатам X для метода генерации (использует кварцевая руда)

     * @param Число для того, чтобы было пустое место по координатам Z для метода генерации (использует кварцевая руда)

     * @param Число, которое настроит максимальную X координату для генерации руды на оси X на чанк

     * @param Число, которое настроит максимальную Z координату для генерации руды на оси Z на чанк

     * @param Максимальное число блоков руды в одной жиле

     * @param Шанс генерации блоков на чанк

     * @param Минимальная координата Y на которой руда может сгенерироваться

     * @param Максимальная координата Y на которой руда может сгенерироваться
     */
	public void addOreSpawn(Block block, World world, Random random, int blockXPos, int blockZPos, int maxX, int maxZ,
		int maxVeinSize, int chancesToSpawn, int minY, int maxY)
	{
		int maxPossY = minY + (maxY - 1);
		assert maxY > minY : "Максимальная Y должна быть больше минимальной";
		assert maxX > 0 && maxX <= 16 : "addOreSpawn: Максимальная X должна быть больше 0 и меньше 16";
		assert minY > 0 : "addOreSpawn: Минимальная Y должна быть больше 0";
		assert maxY < 256 && maxY > 0 : "addOreSpawn: Максимальная Y должна быть меньше 256 и больше 0";
		assert maxZ > 0 && maxZ <= 16 : "addOreSpawn: Максимальная Z должна быть больше 0 и меньше 16";

		int diffBtwnMinMaxY = maxY - minY;
		for (int x = 0; x < chancesToSpawn; x++)
		{
			int posX = blockXPos + random.nextInt(maxX);
			int posY = minY + random.nextInt(diffBtwnMinMaxY);
			int posZ = blockZPos + random.nextInt(maxZ);
			(new WorldGenMinable(block, maxVeinSize)).generate(world, random, posX, posY, posZ);
		}
	}

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

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

Генерация руды в аду Генерация собственносозданной руды Генерация руды в крае

Дополнительные уроки

Локализация названий в игре

Собственно у нас есть некоторые предметы, блоки, а возможно даже кнопки, существа и надписи из нашего мода, называющиеся в инвентаре примерно так: tile.block.name Естественно это нас не устраивает, и это можно исправить, даже не внося изменений в код!

Итак, приступим. Слева, в src/main/resources создайте подпапку assets.mybestmod.lang Понятно, что mybestmod - это краткое имя мода(или modid), указанное в @Mod. Теперь где угодно создайте файл(создайте текстовой, а затем измените расширение) en_US.lang (где будут написаны английские название блоков, предметов и т.д.) и пропишите в нём то, что вы видите вместо названия в инвентаре (в случае нашего первого блока - tile.bestblockever.name), затем равно, и прямо за ним - ваше локализированное название, например: "Best Block EvAR!". То есть должно получиться

tile.bestblockever.name=Best Block EvAR!

Теперь скопируйте файл, и назовите копию ru_RU.lang (собственно русский перевод). Внутри него измените название на русское, например

tile.bestblockever.name=Самый лучший блок!! =P

Теперь оба этих файла можете перетащить в заранее созданную assets.mybestmod.lang При переносе выберите Copy files.

Чтобы локализировать вкладки в режиме творчество добавьте такой код:

itemGroup.tabTutorial=Локализированое имя

tabTutorial - Название вашей вкладки

Вот и всё! Локализация завершена, теперь в игре будут отображаться выбранные вами названия.

Кстати этих названий можно вписывать сколько угодно, главное в столбик.

Дроп определенного предмета при разрушении блока

Всё очень просто. В конец класса созданного вами блока (перед последней фигурной скобкой) вставьте это:

	@Override
    public Item getItemDropped(int par1, Random par2Random, int par3)
    {
        return Items.diamond;
    }

То есть теперь при разрушении вашего блока из него выпадет алмаз. Вы можете написать, чтоб выпадало что угодно. Просто вместо return Items.diamond; напишите "return Blocks." или "return Items.", а после ввода вами точки выпадет список возможных предметов или блоков.

Если хотите, чтоб выпадал не один предмет, а несколько, просто вставьте сразу после предыдущих строк

	
	@Override
    public int quantityDropped(Random par1Random)
    {
        return 20;
    }

Тогда при разрушении выпадет 20 выбранных вами предметов или блоков.

Разносторонняя текстура блока

Я буду использовать следующие текстуры: Нижняя сторона Верхняя сторона Северная часть Южная часть Западная часть Восточная часть

Для этого, добавьте такой код в тело класса:

public IIcon[] icons = new IIcon[6];

И такой после конструктора класса:

@Override
public void registerBlockIcons(IIconRegister reg) {
    for (int i = 0; i < 6; i ++) {
        this.icons[i] = reg.registerIcon(this.textureName + "_" + i);
    }
}

Теперь в папку assets/ID мода/resources/textures/blocks/ добавьте файлы с таким именем: То, что вы указали в скобках в конструкторе класса, в методе this.setTextureName()_код стороны блока

И ещё такой код:

@Override
public IIcon getIcon(int side, int meta) {
    return this.icons[side];
}

В игре блок будет выглядеть так:

Блок с разностороней текстурой в игре

Важно то, что текстура северной и восточной (2 и 5) части блока отображается зеркально. Если вы не поняли, то поставьте блок ТНТ и посмотрите на части, где написано TNT. С одной стороны написано "TNT", а с другой - "ТИТ".

Блок с Разносторонней текстурой (Вид сзади)

Собственная вкладка в Творческом режиме

Для этого добавьте такой код в тело класса:

public static CreativeTabs tabTutorial = new TabTutorial("ModID");

Потом создайте класс TutorialTab. Если всё правильно, то ваш класс будет иметь extends CreativeTabs до первой фигурной скобки. Теперь добавьте этот метод в новосозданный класс:

@Override
@SideOnly(Side.CLIENT)
public Item getTabIconItem()
{
return Item.getItemFromBlock(Blocks.grass);
}

Теперь заходите в игру. Вы увидите свою вкладку во втором списке вкладок, её "символом" будет блок травы. Если вам хочется, чтобы "символом" был предмет, то вместо Blocks. напишите Items.предмет . Если вы хотите, чтобы "символом" был ваш блок или предмет, то напишите BestMod.bestBlockEver . BestMod - главный файл вашего мода. bestBlockEver - ваш блок/предмет.

Собственная вкладка в креативе

Обновление Forge

Чтобы обновить версию Forge, на который вы создаёте моды, необязательно всё перекачивать.

Достаточно просто изменить build.gradle Так что если хотите обновить Forge откройте его любым редактором и найдите строчку

version = "1.7.2-10.12.0.998"

Там будет написана версия Forge, которая у вас сейчас, соответственно вам нужно всего лишь изменить значение на новое. Измените его на версию, до которой хотите обновить Forge (например на 1.7.2-10.12.0.1012) и сохраните файл. Далее запустите gradlew.bat с командой eclipse (то есть запустить bat-файл с кодом gradlew.bat eclipse) и после завершения его работы ваша версия Forge обновлена!

Свой материал для инструмента

Допустим вы хотите, чтобы ваш инструмент обладал свойствами не железной/алмазной кирок из майнкрафта, а собственными.

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

static ToolMaterial NEWMAT = EnumHelper.addToolMaterial("NEWMAT", 2, 564, 5.0F, 4.0F, 50);

Не забудьте про импорт. Давайте разберемся: static означает, что переменная NEWMAT типа ToolMaterial доступна из других классов. Затем приравнивается значению, которое и даст вашей кирке определенные свойства. Теперь об аргументах, перечисленных через запятую:

  1. Название материала
  2. На сколько кирка крута от 0 до 3, то есть какие блоки может ломать(1 - эквивалент каменной, 3 - алмазной).
  3. Максимальное количество сломанных блоков (у алмазной - 1561, каменной - 131).
  4. Скорость добычи (у золотой - 12, у алмазной - 8, деревянной - 2).
  5. Урон, наносимый существам (у деревянной/золотой - 0, железной - 2, алмазной - 3).
  6. Зачаровываемость, то есть какой шанс хороших чар (у золотой - 22, алмазной - 10, железной - 14).

Что ж, теперь можно придать какому-нибудь инструменту эти свойства, для этого в инструменте (например в нашей кирке) измените super(ToolMaterial.EMERALD); на super(BaseMyBestMod.NEWMAT); В таком случае вы отправляете в супер-класс инструмента информацию о том, что свойства описаны переменной NEWMAT типа ToolMaterial, которая описана в классе BaseMyBestMod (или любой другой класс, где она написана).

Вот и всё, свойства инструмента изменены.

Создание брони

Создание брони немного отличается от создания обычных предметов, точнее имеет свои особенности. Приступим.

Мы не будем создавать для каждого предмета свой отдельный класс, а создадим один универсальный, который опишет сразу шлем, нагрудник, штаны и ботинки. Начнём с регистрации переменных.

public static Item bestarmorhelmet;
public static Item bestarmorplate;
public static Item bestarmorpants;
public static Item bestarmorboots;

Шлем, нагрудник, штаны и ботинки соответственно. Теперь описываем эти переменные с помощью универсального класса. Естественно внутри метода preLoad()

bestarmorhelmet = new BestArmor(0, 0).setUnlocalizedName("bestarmorhelmet").setTextureName("mybestmod:BestArmorHelmet");
bestarmorplate = new BestArmor(0, 1).setUnlocalizedName("bestarmorplate").setTextureName("mybestmod:BestArmorPlate");
bestarmorpants = new BestArmor(0, 2).setUnlocalizedName("bestarmorpants").setTextureName("mybestmod:BestArmorPants");
bestarmorboots = new BestArmor(0, 3).setUnlocalizedName("bestarmorboots").setTextureName("mybestmod:BestArmorBoots");

Здесь вроде всё знакомо, мы даём нелокализированное имя каждому из предметов, а также текстуру. Но здесь мы посылаем еще и две цифры в метод BestArmor. Вторая цифра отвечает за тип брони (0 - шлем, 3 - ботинки), назначение первой неясно, но в данном случае она роли не играет. Далее тоже ничего нового, просто зарегистрируем эти предметы в Forge. Сделать это нужно после описания переменных.

GameRegistry.registerItem(bestarmorhelmet, "bestarmorhelmet");
GameRegistry.registerItem(bestarmorplate, "bestarmorplate");
GameRegistry.registerItem(bestarmorpants, "bestarmorpants");
GameRegistry.registerItem(bestarmorboots, "bestarmorboots");

С главным классом работа окончена.

Теперь щелкаем по одной из ошибок и создаём новый класс BestArmor. Теперь "продолжаем" класс ItemArmor, то есть пишем extends ItemArmor после названия класса. Теперь в тело класса вставляем следующее:


	private String texturePath = "mybestmod:textures/model/armor/";
	
	public BestArmor(int id, int armorType) {
		super(ArmorMaterial.DIAMOND, id, armorType);
		this.setCreativeTab(CreativeTabs.tabCombat);
		this.setMaxStackSize(1);
		this.setTextureName();
	}

	public void setTextureName ()
	{
		if(armorType == 0||armorType == 1||armorType == 3){
			this.texturePath += "MyBestArmor_" + 1 + ".png";
		}
		else {
			this.texturePath += "MyBestArmor_" + 2 + ".png";
		}
	}
	
	@Override
	public String getArmorTexture(ItemStack itemstack, Entity entity, int slot, String type){
		return this.texturePath;
	}

Что ж, давайте разбираться.

Первая переменная, просто обозначает начало пути к текстуре брони. Все нужные текстуры можно спокойно извлечь из майнкрафта и отредактировать по желанию. Вот мои отредактированные текстуры: MyBestArmor 1 MyBestArmor 2 BestArmorHelmet BestArmorPlate BestArmorPants BestArmorBoots Текстуры предметов помещаются туда же, где и текстура кирки. А вот две текстуры самой брони нужно поместить в другую папку. Поэтому создайте её: нажмите ПКМ по src/main/resources и выберите New - Package и назовите его assets.mybestmod.textures.model.armor и уже туда перетащите две оставшиеся текстуры.

Давайте дальше разбираться с кодом: следующим идёт метод BestArmor(), в который мы посылаем из главного класса параметры id и armorType. Напомню: от armorType зависит, какая это часть брони. В нём мы посылаем информацию о том, какой материал брони. Я написал, что броня будет аналогична алмазной, но можно создать свой материал для брони и вписать его. Далее мы настраиваем вкладку в креативе. Потом мы ограничиваем максимальное количество данного предмета в одной стопке до одного, чтобы броня не "стакалась". В конце концов мы вызываем созданный нами метод setTextureName()

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

Последний же метод перезаписывает метод супер-класса и указывает майнкрафту, что должна грузиться текстура по пути texturePath, который предварительно был отредактирован во втором методе.

Теперь можно запускать игру и убивать мобов в новых блестящих доспехах!

Свой материал для брони

Почти не отличается от создания собственного материала для инструмента.

В главном классе в любом месте, но вне каких-либо методов пишем:

static ArmorMaterial BESTMAT = EnumHelper.addArmorMaterial("BESTMAT", 100, new int[] {3, 8, 6, 3}, 30);

Затем импортируем ArmorMaterial. Теперь разберём:

  1. BESTMAT - название материала.
  2. 100 - поглощаемый урон.
  3. 3 - защита шлема.
  4. 8 - защита нагрудника.
  5. 6 - защита штанов.
  6. 3 - защита ботинок.
  7. 30 - зачаровываемость.

Вот и все. Теперь можно использовать этот материал для брони, например заменив ArmorMaterial.DIAMOND на BaseMyBestMod.BESTMAT

Примечания

  1. В java директории указываются не слешами, как в Windows, а точками. То есть cpw.mods.fml — это когда папка fml лежит в папке mods, которая лежит в папке cpw.
  2. Любое тело в Java обозначается фигурными скобками и обозначает внутренности некоторой подпрограммы. Например, public class BaseMyBestMod {} указывает, что это класс, а в скобках написано, что он делает.
  3. В Eclipse встроена функция автоматической организации импортируемых классов (Ctrl+⇧ Shift+O).
  4. В Java если строчка написана после двух слешей, то она воспринимается не как код, а как комментарий. Также можно заключить несколько строк в комментарий, закрыв их в конструкцию /*Закомментированный текст*/
  5. С помощью .setUnlocalizedName("bestpickaxe") мы сразу передали методу BestPickAxe информацию, вместо того чтоб в нём писать this.setUnlocalizedName("bestpickaxe") По сути можно все такие аргументы послать через точку.
  6. Когда вы вводите какой-то путь к методу, переменной и т.п. через точку, после ввода точки вы всегда видите возможные продолжения, пользуйтесь этим, чтобы сократить время написания кода, или если не знаете точно, что вам нужно (ориентируйтесь по тому, что посылается в метод и что он возвращает). Если список исчез, всегда, даже когда нет точки, вы можете посмотреть список доступных продолжений, нажав Ctrl + Пробел
  7. Javadoc-комментарии оставляются над методом, классом, переменной и т. д. для того, чтобы описать назначения класса, метода и т. д. Обособляется конструкцией /**Javadoc-комментарий*/