Создание модификаций с помощью Forge/1.7+/Дополнительные уроки
Здесь представлены основные уроки по созданию модификаций с помощью Forge/1.7+. Остальную информацию по данной теме смотрите в соответствующей статье.
Локализация названий в игре
Собственно у нас есть некоторые предметы, блоки, а возможно даже кнопки, существа и надписи из нашего мода, называющиеся в инвентаре примерно так: item.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
— Название вашей вкладки
Вот и всё! Локализация завершена, теперь в игре будут отображаться выбранные вами названия.
Подобных названий можно вписывать сколько угодно, главное в столбик.
Скорее всего в игре русское название будет выглядеть вопросами! Это всё из-за кодировки. Исправить это можно зайдя в eclipse вкладку window\preferences\general и просто нажмите на workspace и внизу найдите text file encoding и поставьте на other и там выберите UTF-8. Всё! теперь у нас нормальный русский язык!
Дроп определённого предмета при разрушении блока
Всё очень просто. В конец класса созданного вами блока (перед последней фигурной скобкой) вставьте это:
@Override
public Item getItemDropped(int par1, Random par2Random, int par3)
{
return Items.diamond;
}
То есть теперь при разрушении вашего блока из него выпадет алмаз. Вы можете написать, чтоб выпадало что угодно. Просто вместо
return Items.diamond;
напишите «return Item.getItemFromBlock(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.setBlockTextureName()>_<код стороны блока>
И ещё такой код:
@Override
public IIcon getIcon(int side, int meta) {
return this.icons[side];
}
В игре блок будет выглядеть так:
Важно то, что текстура северной и восточной (2 и 5) части блока отображается зеркально. Если вы не поняли, то поставьте блок ТНТ и посмотрите на части, где написано TNT. С одной стороны написано «TNT», а с другой — «ТИТ».
Собственная вкладка в Творческом режиме
Для этого добавьте такой код в тело класса:
public static CreativeTabs tabTutorial = new TabTutorial("ModID");
«ModID» заменяем на любое число. Рекомендую ID больше 11 (12 ID сразу на следующей странице творческого инвентаря).
Потом создайте класс TutorialTab. Если всё правильно, то ваш класс будет иметь extends CreativeTabs
до первой фигурной скобки. Теперь добавьте этот метод в ново-созданный класс:
public TabTutorial(String lable) {
super(lable);
}
@Override
public Item getTabIconItem()
{
return Item.getItemFromBlock(Blocks.grass);
}
Теперь заходите в игру. Вы увидите свою вкладку во втором списке вкладок, её «символом» будет блок дёрна. Если вам хочется, чтобы «символом» был предмет, то вместо Blocks.
напишите Items.предмет
. Если вы хотите, чтобы «символом» был ваш блок или предмет, то напишите BestMod.bestBlockEver
. BestMod
— главный файл вашего мода. bestBlockEver
— ваш блок/предмет.
Для того что бы добавить что либо из вашего мода в собственную вкладку пишем:
this.setCreativeTab(НазваниеГлавногоКласса.НазваниеВашейВкладки);
Обновление 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 обновлена!
Обновление ForgeGradle
Forge отделён от ForgeGradle, поэтому если вы попытаетесь обновиться на версию Forge, которая использует более новой ForgeGradle, вы получите ошибки. Вот таблица версия Forge, и какие версии ForgeGradle он использует.
ForgeGradle | Forge |
---|---|
- | 959<, 965 |
1.0 | 960-964 |
1.1 | 967-1047 |
1.2 | 1048+ |
Удалите папку .gradle, которая находится в папке, куда вы разархивировали Forge. Теперь, откройте файл build.gradle (который находится там же). Найдите такую строку:
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:1.x-SNAPSHOT'
}
В 1.x-SNAPSHOT, поменяйте 1.x на нужную версию ForgeGradle. Сохраните файл и откройте командную строку. Повторно введите команды, которые вы использовали при установке Forge. ForgeGradle обновит все нужные файлы.
Свой материал для инструмента
Допустим вы хотите, чтобы ваш инструмент обладал свойствами не железной/алмазной кирок из майнкрафта, а собственными.
Тогда где-нибудь(вы можете где угодно написать эту строку, главное, чтоб можно было вызвать.), например в главном классе вне каких либо методов (то есть можно перед последней фигурной скобкой) напишите:
public static final ToolMaterial NEWMAT = EnumHelper.addToolMaterial("NEWMAT", 2, 564, 5.0F, 4.0F, 50);
Не забудьте про импорт. Давайте разберемся: static означает, что переменная NEWMAT типа ToolMaterial доступна из других классов. Затем приравнивается значению, которое и даст вашей кирке определённые свойства. Теперь об аргументах, перечисленных через запятую:
- Название материала
- На сколько кирка крута от 0 до 3, то есть какие блоки может ломать(1 — эквивалент каменной, 3 — алмазной).
- Максимальное количество сломанных блоков (у алмазной — 1561, каменной — 131).
- Скорость добычи (у золотой — 12, у алмазной — 8, деревянной — 2).
- Урон, наносимый существам (у деревянной/золотой — 0, железной — 2, алмазной — 3).
- Зачаровываемость, то есть какой шанс хороших чар (у золотой — 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;
}
Что ж, давайте разбираться.
Первая переменная, просто обозначает начало пути к текстуре брони. Все нужные текстуры можно спокойно извлечь из майнкрафта и отредактировать по желанию. Вот мои отредактированные текстуры:
Текстуры предметов помещаются туда же, где и текстура кирки. А вот две текстуры самой брони нужно поместить в другую папку. Поэтому создайте её: нажмите ПКМ по 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. Теперь разберём:
- BESTMAT — название материала.
- 100 — прочность (железо — 15, алмазы — 33).
- 3 — защита шлема.
- 8 — защита нагрудника.
- 6 — защита штанов.
- 3 — защита ботинок.
- 30 — зачаровываемость.
Вот и все. Теперь можно использовать этот материал для брони, например заменив ArmorMaterial.DIAMOND
на BaseMyBestMod.BESTMAT
Генерация предметов в контейнерах натуральных структур
Итак, вы можете сделать так, чтобы ваш, или любой другой предмет/блок генерировался в сундуках сокровищницы. Для этого в методе preLoad() в главном классе вставьте следующее:
ChestGenHooks.addItem(ChestGenHooks.DUNGEON_CHEST,
new WeightedRandomChestContent(new ItemStack(BaseMyBestMod.bestblockever), 1, 10, 3));
Разберемся в параметрах:
(ChestGenHooks.DUNGEON_CHEST)
— ВместоDUNGEON_CHEST
выберете одно из возможных мест генерации в выпадающем списке.(BaseMyBestMod.bestblockever)
— Требуемый блок/предмет. В скобках указывается любая переменная типа Block или Item.(1)
— Минимальное генерируемое количество.(10)
— Максимальное генерируемое количество.(3)
— Шанс генерации.
Атрибуты для моба
Если вы уже проверили моба, то заметили, что он двигается очень медленно. Чтобы исправить это и изменить атрибуты для моба, добавьте в его класс следующий код:
@Override
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(20.0D);
this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(32.0D);
this.getEntityAttribute(SharedMonsterAttributes.knockbackResistance).setBaseValue(0.0D);
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.25D);
this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setBaseValue(2.0D);
}
Разъяснение:
Параметр | Описание |
---|---|
maxHealth | Максимальное здоровье |
followRange | Дистанция, на которой моб будет преследовать кого-либо |
knockbackResistance | Сопротивление к отбрасыванию |
movementSpeed | Скорость движения |
attackDamage | Сила атаки |
Атрибуты установлены.
Интеллект для моба
Теперь моб будет просто двигаться, но ничего не делать. Для того, чтобы добавить ему интеллект создайте в класс моба следующий код:
public boolean isAIEnabled()
{
return true;
}
Теперь в конструктор класса добавьте следующий код:
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.2D, false));
this.tasks.addTask(3, new EntityAIWander(this, 1.0D));
this.tasks.addTask(4, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(5, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 0, true));
Первый аргумент метода «addTask» — приоритет назначения интеллекта, второй — сам интеллект. В примере используются следующие интеллекты: «Swimming», «AttackOnCollid», «Wander», «WatchClosest», «LookIdle», «HurtByTarget» и «NearestAttackableTarget». Разъяснение:
Интеллект | Описание |
---|---|
Swimming | Может ли существо плавать? |
AttackOnCollid | Базовый тип атаки, который используют зомби и пауки. |
Wander | Существо будет ходить вокруг, когда никого не атакует. |
WatchClosest | Ищет назначенное существо на заданном расстоянии. |
LookIdle | Существо будет осматриваться, просто стоя. |
HurtByTarget | Сделает целью какого-либо моба, который его ударил. |
NearestAttackableTarget | Ищет любое существо, которое подходит по второму параметру. |
Интеллект установлен.
Свой скин при моддинге
Внимание! Этот способ работает только на лицензионной версии Minecraft.
Чтобы при создании мода вы видели свой скин, вместо стандартного скина Steve, нужно прописать 2 строчки в аргументы запуска.
--username=ВашЛогин
--password=ВашПароль
После этого, при заходе в игру вы будете видеть свой скин.