Сегодня мы создаем блок!
Перед @Init пишем:
public static Block TutBlock;
TutBlock название может быть другим
Внутри метода
public void load пишем это:
TutBlock = new TutBlock(700, Material.rock).setStepSound(Block.soundWoodFootstep).setHardness(2.5F).setCreativeTab(CreativeTabs.tabBlock).setUnlocalizedName("TutBlock");
GameRegistry.registerBlock(TutBlock);
LanguageRegistry.addName(TutBlock, "Tutorial Block");
Разберем!:TutBlock = new TutBlock - регистрируем блок в файле TutBlock(второй)
500 - ID блока
Material.rock - материал блока камень
.setStepSound(Block.soundWoodFootstep) - звук хотьбы по блоку (у нас дерево)
.setHardness(2.5F) - твердость блока (у камня например 1.5F, у обсидиана 50F)
.setCreativeTab(CreativeTabs.tabBlock) - вкладка креатива - блоки
.setUnlocalizedName("TutBlock") - если не будет указано другое имя (LanguageRegistry) то будет TutBlock
LanguageRegistry.addName(TutBlock, "Tutorial Block") - добавление имени Tutorial Block блоку TutBlock
P.S. если лезут ошибки наведите курсор на подчеркнутый тест и импортируйте нужное или нажмите "ctrl + shift + o"
Разобрали. Создадим класс TutBlock:
package ru.tutmod.src;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.src.*;
import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
public class TutBlock extends Block {
public TutBlock(int par1, Material par2Material) {
super(par1, par2Material);
}
public void registerIcons(IconRegister par1IconRegister)
{
this.blockIcon = par1IconRegister.registerIcon("TutMod:TutBlock");
}
}
Разберем!package ru.tutmod.src; - папка где лежит файл
import... - импорты
public TutBlock(int par1, Material par2Material) {super(par1, par2Material);} - публикация класса, с int'ами: "par1" - id блока, "par2Material" - материал блока
public void registerIcons(IconRegister par1IconRegister){this.blockIcon = par1IconRegister.registerIcon("TutMod:TutBlock");}
- а тут у нас самое интересное - иконка! Она будет лежать по пути ...\ваша_папка_с_mcp\src\minecraft\mods\TutMod\textures\blocks\TutBlock.png
Заходим и проверяем Вот код базы TutModCore
package ru.tutmod.src;
import net.minecraft.block.material.Material;
import net.minecraft.src.*;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
@Mod (modid = "TutMod", name = "Tutorial Mod", version="0.0.1")
public class TutModCore {
public static Block TutBlock;
@Init
public void load(FMLInitializationEvent event)
{
TutBlock = new TutBlock(700, Material.rock).setStepSound(Block.soundWoodFootstep).setHardness(2.5F).setCreativeTab(CreativeTabs.tabBlock).setUnlocalizedName("TutBlock");
GameRegistry.registerBlock(TutBlock);
LanguageRegistry.addName(TutBlock, "Tutorial Block");
}
@PreInit
public void init(FMLPreInitializationEvent preEvent){}
}
Будем использовать блок который сделали во 2 уроке как руду!
ГенерацияСначала регистрируем нашу генерацию для руды.
После load пишем:
GameRegistry.registerWorldGenerator(new WorldgeneratorTut());
И создаем новый класс WorldgeneratorTutorial (Ну или другое название, тогда поменяйте и в строке регистрации).
И пишем там это.
package ru.tutmod.src;
import java.util.Random;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenMinable;
import cpw.mods.fml.common.IWorldGenerator;
public class WorldgeneratorTut implements IWorldGenerator
{
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: generateSurface(world, random, chunkX*16, chunkZ*16);
}
}
public void generateSurface(World world, Random random, int chunkX, int chunkZ)
{
for(int i=0; i < 300; i++)
{
int randPosX=chunkX + random.nextInt(16);
int randPosY=random.nextInt(230);
int randPosZ=chunkZ + random.nextInt(16);
(new WorldGenMinable(TutModCore.TutBlock.blockID, 4)).generate(world, random, randPosX, randPosY, randPosZ);
}
}
private void generateNether(World world, Random random, int chunkX, int chunkZ)
{
}
}
Нас интересует этот кусок
public void generateSurface(World world, Random random, int chunkX, int chunkZ)
{
for(int i=0; i < 300; i++)
{
int randPosX=chunkX + random.nextInt(16);
int randPosY=random.nextInt(230);
int randPosZ=chunkZ + random.nextInt(16);
(new WorldGenMinable(TutModCore.TutBlock.blockID, 4)).generate(world, random, randPosX, randPosY, randPosZ);
}
}
Разберем!
Там где цифра 300 - это частота появления. 300 - это будет этой руды дофига.
Что бы была нормальная руда, это 10 - 25.
Там где 230, это высота на какой она появляется (от админиума).
С этим экспериментируйте. ( К примеру алмазы появляются от 20 и ниже).
TutModCore.TutBlock.blockID, 4
И самая последняя строка. Это блок и количество его в одном месте.
Вполне все просто. Дроп с рудыПросто добавляем это в блок
public int idDropped(int par1, Random par2Random, int par3)
{
return TutModCore.TutItem.itemID;
}
TutMod.TutItem.itemID - это то что будет выпадет с руды.
Что бы выпадал не один предмет а больше, добавим это.
public int quantityDropped(Random par1Random)
{
return 2;
}
Будет выпадать 2 предмета, меняйте число по своему желанию.
5.Рецепты
Допустим вы сделали предмет и хотите его скрафтить. Сейчас этим займемся!
Добавим в
load это
GameRegistry.addRecipe(new ItemStack(Item.diamond, 64), new Object[]{
"###",
"#X#",
"#Q#",
Character.valueOf('X'), Block.cobblestone, Character.valueOf('#'), Block.dirt});
Объясню, мы добавили крафт при помощи булыжника(cobblestone), земли(dirt)иии... ничего(Q) у нас получиться алмазик(diamond) в количестве - 64 шт.\
Ну все же рассмотрим поближе.
(new ItemStack(Item.diamond, 64)
тут мы пишем что хотим создать и его количество.
Что бы создать свой блок или предмет из мода, нужно писать так:
(new ItemStack(TestModCore.TutItem, 1)
А теперь печка! В
load :
GameRegistry.addSmelting(Block.dirt.blockID, new ItemStack(Item.coal, 1), 1.0F);
Здесь, мы добавили рецепт в печку, в котором при обжарке земли(dirt), мы получим уголь(coal), в количестве - 1 шт.
Тут уже должны вы сами понять.
6.Еда
Сегодня мы добавим еду и супчик
!
Регистрируем еду и супчик!
public static Item TutFood;//Еда
public static Item TutSoup;//Супчик
TutFood = new TutFood(5005, 1, 0.4F, false).setUnlocalizedName("testFood");//Еда
TutSoup = new TutSoup(5004, 2).setUnlocalizedName("testSoup");//Суп
Разберем!В еде:
5005 - ID
1 - количество восполняемых пунктов сытости.
0.4F - лучше не трогать.
false - нельзя скормить собакам. Если true то можно.
В супе:
5004 - ID
2 - количество восполняемых пунктов сытости.
Далее даем названия нашим предметам.
LanguageRegistry.addName(TutFood, "Батончик Майнс");
LanguageRegistry.addName(TutSoup, "Суп Ролтон");
Создаем классы
TutFood и
TutSoup.
Содержимое TutFood
package ru.tutmod.src;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.item.ItemFood;
//Мы поставили родитель ItemFood, и теперь наша еда автоматически будет в категории tabFood.
public class TutFood extends ItemFood
{
public TutFood(int par1, int par2, float par3, boolean par4)
{
super(par1, par2, par4);
maxStackSize = 64;
}
public void registerIcons(IconRegister par1IconRegister)
{
this.itemIcon = par1IconRegister.registerIcon("TutMod:TutFood");
}
}
Содержимое TutFood
package ru.tutmod.src;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class TutSoup extends ItemFood
{
public TutSoup(int par1, int par2)
{
super(par1, par2, false);
this.setMaxStackSize(1);
}
public ItemStack onEaten(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
{
super.onEaten(par1ItemStack, par2World, par3EntityPlayer);
return new ItemStack(Item.bowlEmpty);//То что будет оставаться после съедения супа.
}
public void registerIcons(IconRegister par1IconRegister)
{
this.itemIcon = par1IconRegister.registerIcon("TutMod:TutSoup");
}
}
Тут, кто изучал мои уроки, все поймет
7. Создание своей вкладки в креативе (Creative Tab)
В данном уроке мы разберём создание своей вкладки в креативе. Ну что, приступим!
Добавляем регистрацию нашей вкладки
public static CreativeTabs tabTut= new TabTut(CreativeTabs.getNextID(),"TutorialCreativeTab");
После
public class TutModCore {
Видим ошибку с CreativeTabs. Добавим импорт(ctrl+shift+o/наводим на ошибку и импортируем/вставляем код ниже)
import net.minecraft.creativetab.CreativeTabs;
Видим еще ошибку но уже с TabTut. Создаем класс!
И вставляем это
package ru.tutmod.src;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import cpw.mods.fml.relauncher.*;
public class TabTut extends CreativeTabs {
public TabTut(int position, String tabID)
{
super(position, tabID);
}
@SideOnly(Side.CLIENT)
public int getTabIconItemIndex()
{
return TutModCore.TutItem.itemID;
}
public String getTranslatedTabLabel()
{
return "TutMod";
}
}
Разберем!
public TabTut(int position, String tabID)
{
super(position, tabID);
}
Это конструктор вкладки
public int getTabIconItemIndex()
{
return TutModCore.TutItem.itemID;
}
Значком нашей вкладки будет TutItem, который мы добавили выше
public String getTranslatedTabLabel()
{
return "TutMod";
}
Называться в игре вкладка будет TutMod(если вы русифицировали мод, то можно и по-русски назвать
)
Заходим и тестим!
8.Инструменты
Для начала зарегистрируем материал, который определяет прочность, силу, уровень и тд. у инструментов.
public static EnumToolMaterial TutMATERIAL = EnumHelper.addToolMaterial("TutMATERIAL", 2, 500, 7F, 3, 9);
Что бы не было ошибки не забудьте импортировать пакет.
Разберем строку.
TutMATERIAL - переменная материала.
"TutMATERIAL" - Имя материала
2 - Уровень инструментов(3 - Алмазы,2 - Железо,1 - Камень,0 - Дерево и золото)
500 - Количество использований
7F - Скорость работы
3 - Урон по мобам
9 - Чем больше цифра, тем лучше зачарования выпадают.
Теперь добавим сам инструмент, например кирку.
public static Item TutPickaxe;
TutPickaxe = new TutPickaxe(5007, TutMATERIAL).setCreativeTab(CreativeTabs.tabTools).setUnlocalizedName("TutPickaxe");
В принципе вы все должны понять.
Теперь создаем класс TutPickaxe (Ну или как вы там назвали).
И пишем там это:
package ru.tutmod.src;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.item.EnumToolMaterial;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.src.*;
public class TutPickaxe extends ItemPickaxe
{
public TutPickaxe(int i, EnumToolMaterial material)
{
super(i, material);
}
public void registerIcons(IconRegister par1IconRegister)
{
this.itemIcon = par1IconRegister.registerIcon("TutMod:TutPickaxe");
}
}
В принципе тут все понятно, но надо разобрать третью строку:
public class TutPickaxe extends ItemPickaxe
Как видим тут написано для кирки (ItemPickaxe)
А вот другие на названия инструмента.
На название инструмента:
Для лопаты - extends ItemSpade
Для кирки - extends ItemPickaxe
Для топора - extends ItemAxe
Для Меча - extends ItemSword
Для мотыги - extends ItemHoe
То есть все аналогично.
Далее надо зарегистрировать имя кирке и дать ей рецепт.
Если чего то не поняли, внимательно прочитайте про предмет.
9.Config файл
Наверное это самое громадное достоинство Forge. Легко создаваемые конфиги.
Что бы избежать несовместимость модов из за ID для этого и существуют конфиги.
И так, начнем!
Сначало нам нужно увидеть конфиг, если он есть - прочитать, нету - создать.
Но это нужно делать перед тем, как к блокам и предметам будут добавляться рецепты, имена и тому подобные вещи. Поэтому создаем функцию, которая будет загружаться перед той, в которой это все делается:
@PreInit
public void load(FMLPreInitializationEvent event) {
}
Далее сам конфиг(в функцию, описаную выше)
Configuration config = new Configuration(event.getSuggestedConfigurationFile());
Здесь создается переменная, отвечающая за файл конфигурации вместе с самим файлом.
Но создать мало - нужно же еще прочитать и сохранить его, верно?
config.load();
config.save();
Теперь осталось только прописать туда то, что нам нужно. Пишем между
config.load() и
config.save():
TutBlockID = config.getBlock("TutBlock", 500).getInt();
TutItemID = config.getItem("TutItem", 1000).getInt();
Разберем одну из строк
TutBlockID = config.getBlock("TutBlock", 500).getInt();
"TutBlock" - название, которое будет отображаться в config файле;
500 - стандартное значение ID, устанавливаемое, если не указано(конфиг файл поврежден или еще не создан).
getInt() - преобразование получившегося значения в тип Integer, который используется как ID блоков или предметов.
getBlock - ID блока,
getItem - соответственно, ID предмета.
Теперь, когда мы создали этот файл, нужно прикрутить ID, которые в нем указаны, к предметам и блокам.
Заместо ID пишем TutBlockID и TutItemID соответственно. Для еды учитесь создавать сами (На примере конфига для предметов).
TutBlock = new TutBlock(TutBlockID, Material.rock).setStepSound(Block.soundWoodFootstep).setHardness(2.5F).setCreativeTab(CreativeTabs.tabBlock).setUnlocalizedName("TutBlock");
TutItem = new TutItem(TutItemID, 10).setCreativeTab(CreativeTabs.tabMaterials).setUnlocalizedName("TutItem");
И регистрируем ID (туда где зарегистрирован блок, итем и т.д.)
public static int TutBlockID;
public static int TutItemID;
10.Броня
Регистрируем броню
public static Item Tuthelm;
public static Item Tutplate;
public static Item Tutlegs;
public static Item Tutboots;
Tuthelm = new TutArmor(TuthelmID, 0).setCreativeTab(CreativeTabs.tabCombat).setUnlocalizedName("Tuthelm");
Tutplate = new TutArmor(TutplateID, 1).setCreativeTab(CreativeTabs.tabCombat).setUnlocalizedName("Tutplate");
Tutlegs = new TutArmor(TutlegsID, 2).setCreativeTab(CreativeTabs.tabCombat).setUnlocalizedName("Tutlegs");
Tutboots = new TutArmor(TutbootsID, 3).setCreativeTab(CreativeTabs.tabCombat).setUnlocalizedName("Tutboots");
0,1,2,3 - шлем, нагрудник, поножи, ботинки
Создаем класс TutArmor
package ru.tutmod.src;
import cpw.mods.fml.common.registry.LanguageRegistry;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.*;
import net.minecraft.util.Icon;
import net.minecraft.world.World;
import net.minecraftforge.common.IArmorTextureProvider;
public class TutArmor extends ItemArmor implements IArmorTextureProvider{
private static int[] damageReductionAmountArray = new int[] {2, 7, 5, 2};
private int damageReduceAmount;
public TutArmor(int i, int j)
{
super(i, EnumArmorMaterial.CHAIN, 5, j);
damageReduceAmount = damageReductionAmountArray[j];
setMaxDamage(66);
}
public void registerIcons(IconRegister par1IconRegister)
{
if(this == TutMod.Tuthelm){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tuthelm");
}
if(this == TutMod.Tutplate){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tutplate");
}
if(this == TutMod.Tutlegs){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tutlegs");
}
if(this == TutMod.Tutboots){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tutboots");;
}
return;
}
@Override
public String getArmorTextureFile(ItemStack itemstack) {
if(itemstack.itemID == TutMod.Tuthelm.itemID || itemstack.itemID == TutMod.Tutplate.itemID || itemstack.itemID == TutMod.Tutboots.itemID){
return "/mods/TutMod/textures/armor/TutArmor_1.png";
}
if(itemstack.itemID == TutMod.Tutlegs.itemID){
return "/mods/TutMod/textures/armor/TutArmor_2.png";
}
else return null;
}
}
Разбираем!
private static int[] damageReductionAmountArray = new int[] {2, 7, 5, 2};
2 - это защита шлема
7 - нагрудника
5 - понож
2 - сапогов
setMaxDamage(66);
Прочность брони
public void registerIcons(IconRegister par1IconRegister)
{
if(this == TutMod.Tuthelm){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tuthelm");
}
if(this == TutMod.Tutplate){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tutplate");
}
if(this == TutMod.Tutlegs){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tutlegs");
}
if(this == TutMod.Tutboots){
this.itemIcon = par1IconRegister.registerIcon("TutMod:Tutboots");;
}
return;
}
Тут думаю понятно, иконки для брони
public String getArmorTextureFile(ItemStack itemstack) {
if(itemstack.itemID == TutMod.Tuthelm.itemID || itemstack.itemID == TutMod.Tutplate.itemID || itemstack.itemID == TutMod.Tutboots.itemID){
return "/mods/TutMod/textures/armor/TutArmor_1.png";
}
if(itemstack.itemID == TutMod.Tutlegs.itemID){
return "/mods/TutMod/textures/armor/TutArmor_2.png";
}
else return null;
}
Это текстуры для брони. Думаю все понятно.
Дальше даем имена броне(в главный класс)
LanguageRegistry.addName(Tuthelm, "Учебный шлем");
LanguageRegistry.addName(Tutplate, "Учебная кирасса");
LanguageRegistry.addName(Tutlegs, "Учебные поножи");
LanguageRegistry.addName(Tutboots, "Учебные сапоги");
Далее регистрируем рендер(ну чтобы на игроке была видна броня)
RenderPlayer.armorFilenamePrefix = new String[] { "cloth", "chain", "iron", "diamond", "gold", "TutArmor" };
Если у вас не одна броня а больше то строка выглядит так
RenderPlayer.armorFilenamePrefix = new String[] { "cloth", "chain", "iron", "diamond", "gold", "TutArmor", "Еще броня" };
Ну с конфигами думаю раберетесь
Продолжение тут
Спасибо! Будут добавляться еще уроки а пока у меня кончается интернет... я продлил трафик
Жду ваших плюсиков в репу!
P.S.не надо мне говорить что уже есть уроки Фирста! Эти уроки являются трудами разных модмейкеров, в том числе и меня. То бишь некоторые уроки я взял с разных сайтов в том числе и зарубежных и переписал их с комментариями, которые будут понятны новичкам. В общем удачи в моддинге!