- 329
- 13
Перед прочтением крайне рекомендую посетить Учебник по моддингу - там информации намного больше.
Код, представленный ниже, актуален для Minecraft v1.7.2 и Forge v.10.12.0.1024. Начнем мы с самого простого: регистрация блока в основном классе мода и создание "каркаса" блока.
Тут все довольно просто, достаточно добавить 3 строки в шаблон основного класса мода. Обратите лишь внимание на то, что регистрация блока происходит в preInit(FMLPreInitializationEvent event). Строчкой BlockTest = new BlockTest(Material.rock) мы привязали наш BlockTest к конкретному классу, которого еще нет. Создадим его.
Код, представленный ниже, актуален для Minecraft v1.7.2 и Forge v.10.12.0.1024. Начнем мы с самого простого: регистрация блока в основном классе мода и создание "каркаса" блока.
Код:
@Mod(modid = TaoModMain.MODID, version = TaoModMain.VERSION)
public class TaoModMain
{
public static final String MODID = "tutorialblockmod";
public static final String VERSION = "1.0";
// Объявляем новый блок
public static Block BlockTest;
@EventHandler
public void preInit(FMLPreInitializationEvent event)
{
// Определяем, что BlockTest - это блок с материалом "Камень (rock)"
// Далее регистрируем его в Forge под уникальным именем "testblock"
BlockTest = new BlockTest(Material.rock);
GameRegistry.registerBlock(BlockTest, "testblock");
}
}
Создадим класс блока, который от нас требует Forge. Старайтесь придерживаться такой же иерархии, как и в ванильных файлах Minecraft. Создайте пакет block а в нем класс BlockTest.
Шаблон готов. Теперь можно проверить его в игре. Заходим в игру, создаем креатив, и теперь во вкладке с блоками появился новый блок без текстуры.
Код:
public class BlockTest extends Block
{
// Конструктор класса
public BlockTest(Material material)
{
super(material);
// Указываем вкладку креатива, в которой будет наш блок (вкладка Блоки, можно указать любую)
setCreativeTab(CreativeTabs.tabBlock);
// Указываем имя для блока (понадобится для локализации)
setBlockName(TaoModMain.MODID + "." + "testblock");
}
}
Наш новый блок не имеет текстуры, вместо нее отображается стандартная фиолетово-черная сетка. Мы исправим это, добавив текстуру. Для примера я взял следующую:
Теперь ее нужно добавить в нужное место, а именно в
src/main/resource/assets/имя_мода/textures/blocks/blocktest.png
Теперь модифицируем шаблон следующим образом:
Смотрим на результат:
Теперь ее нужно добавить в нужное место, а именно в
src/main/resource/assets/имя_мода/textures/blocks/blocktest.png
Теперь модифицируем шаблон следующим образом:
Код:
public class BlockTest extends Block
{
// Объявляем текстуру для блока
@SideOnly(Side.CLIENT)
protected IIcon BlockTestTexture;
// Конструктор класса
public BlockTest(Material material)
{
super(material);
// Указываем вкладку креатива, в которой будет наш блок (вкладка Блоки, можно указать любую)
setCreativeTab(CreativeTabs.tabBlock);
// Указываем имя для блока (понадобится для локализации)
setBlockName(TaoModMain.MODID + "." + "testblock");
}
// Этот метод позволяет зарегистрировать новые текстуры
@SideOnly(Side.CLIENT)
@Override
public void registerBlockIcons(IIconRegister par1IconRegister)
{
// Регистрируем путь до png-текстуры
BlockTestTexture = par1IconRegister.registerIcon(TaoModMain.MODID + ":" + "blocktest");
}
// Этот метод получает текстуры блока
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon(int par1int, int par2int)
{
return BlockTestTexture;
}
}
Теперь сделаем так, чтобы текстура нашего блока с разных сторон отличалась. Для этого нам придется дорисовать еще текстуры для боковых, а также верхней и нижней граней блока:
-
-
Теперь мы должны их зарегистрировать и поставить условия для отрисовки текстур, а также воспользуемся методом onBlockPlacedBy, где рассчитаем угол поворота игрока по горизонтали:
Проверяем результат.
Теперь мы должны их зарегистрировать и поставить условия для отрисовки текстур, а также воспользуемся методом onBlockPlacedBy, где рассчитаем угол поворота игрока по горизонтали:
Код:
@SideOnly(Side.CLIENT)
@Override
public void registerBlockIcons(IIconRegister par1IconRegister)
{
// Регистрируем путь до png-текстур для разных сторон блока
BlockTestFront = par1IconRegister.registerIcon(TaoModMain.MODID + ":" + "blocktest_front");
BlockTestSide = par1IconRegister.registerIcon(TaoModMain.MODID + ":" + "blocktest_side");
BlockTestTop = par1IconRegister.registerIcon(TaoModMain.MODID + ":" + "blocktest_top");
}
// Этот метод определяет, на какую грань блока накладывать ту или иную текстуру
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon(int par1int, int par2int)
{
return par1int == 1 ? BlockTestTop : (par1int == 0 ? BlockTestTop : (par2int == 2 && par1int == 2 ? BlockTestFront : (par2int == 3 && par1int == 5 ? BlockTestFront : (par2int == 0 && par1int == 3 ? BlockTestFront : (par2int == 1 && par1int == 4 ? BlockTestFront : BlockTestSide)))));
}
// Когда мы поставим блок - будет вызван этот метод
@Override
public void onBlockPlacedBy(World par1World, int par2int, int par3int, int par4int, EntityLivingBase par5EntityLivingBase, ItemStack par6ItemStack)
{
// Ниже мы определяем угол поворота игрока
// И определяем, куда будет повернут блок
int i = MathHelper.floor_double((double)(par5EntityLivingBase.rotationYaw * 4.0F / 360.0F) + 2.5D) & 3;
par1World.setBlockMetadataWithNotify(par2int, par3int, par4int, i, 2);
}
Также можно изменить свойства блока, такие как прочность блока, устойчивость к взрыву, звук при ходьбе по блоку и необходимый для добычи инструмент. Это все мы будем настраивать в конструкторе блока.
setHardness(1.0F) - прочность блока. Определяет, насколько долго нужно долбить блок, чтобы он был разрушен. Таблицу прочности блоков можно посмотреть здесь.
setResistance(20.0F) - устойчивость блока к взрывам. Таблицу устойчивости можно посмотреть здесь.
setHarvestLevel("pickaxe", 3) - условия добычи блока. В нашем случае, если не добывать блок алмазной киркой, то он не выпадет в виде дропа.
setLightLevel(12.0F) - определяет свечение блока. Яркость стандартных блоков можно посмотреть здесь здесь.
setStepSound(Block.soundTypeStone) - определяет тип звука, издаваемый когда игрок ходит по этому блоку.
Код:
// Конструктор класса
public BlockTest(Material material)
{
super(material);
setCreativeTab(CreativeTabs.tabBlock);
setBlockName(TaoModMain.MODID + "." + "testblock");
setHardness(1.0F);
setResistance(20.0F);
setHarvestLevel("pickaxe", 3);
setLightLevel(12.0F);
setStepSound(Block.soundTypeStone);
}
setResistance(20.0F) - устойчивость блока к взрывам. Таблицу устойчивости можно посмотреть здесь.
setHarvestLevel("pickaxe", 3) - условия добычи блока. В нашем случае, если не добывать блок алмазной киркой, то он не выпадет в виде дропа.
setLightLevel(12.0F) - определяет свечение блока. Яркость стандартных блоков можно посмотреть здесь здесь.
setStepSound(Block.soundTypeStone) - определяет тип звука, издаваемый когда игрок ходит по этому блоку.
По умолчанию при попытке добыть этот блок мы получаем его же. Попробуем изменить это и сделать, например, выпадение светопыли. Для этого добавим вот такой метод:
Теперь при добыче с блока будет падать одна светопыль.
А теперь сделаем так, чтобы при добыче выпадало несколько штук светопыли. Тут нам поможет добавление еще одного метода:
return par2Random.nextInt(4) + 1 - это означает что точно выпадет 1 и, возможно, еще от 0 до 3 дополнительно.
Код:
// Метод, устанавливающий что будет падать с блока
@Override
public Item getItemDropped(int par1int, Random par2int, int par3int)
{
return Items.glowstone_dust;
}
А теперь сделаем так, чтобы при добыче выпадало несколько штук светопыли. Тут нам поможет добавление еще одного метода:
Код:
// Метод, устанавливающий количество выпадающих с блока вещей
@Override
public int quantityDroppedWithBonus(int par1int, Random par2Random)
{
return par2Random.nextInt(4) + 1;
}
Теперь сделаем так, чтобы при нажатии правой кнопкой мыши на блок происходили какие-то действия. В качестве примера сделаем постепенное увеличение яркости блока. За использование блока отвечает метод onBlockActivated:
Теперь кликая на блок - получаем разное свечение.
Код:
// Действие на правую кнопку мыши
@Override
public boolean onBlockActivated(World par1World, int par2int, int par3int, int par4int, EntityPlayer par5EntityPlayer, int par6int, float par7float, float par8float, float par9float)
{
// Если яркость блока еще не максимум - увеличиваем ее.
// Если максимум - сбрасываем яркость на ноль.
if (getLightValue() < 15)
{
setLightLevel((this.getLightValue() / 15.0F) + 0.067F);
}
else
{
setLightLevel(0);
}
return true;
}
Теперь сделаем так, чтобы при установке этого блока на блок шерсти они образоввывали живого крипера. То бишь сделаем аналог снеговика. Воспользуемся методом onBlockActivated:
Проверяем результат.
Код:
// Метод, вызываемый в момент установки блока
@Override
public void onBlockAdded(World par1World, int par2int, int par3int, int par4int)
{
// Проверяем, есть ли под нашим блоком шерсть
if (par1World.getBlock(par2int, par3int - 1, par4int) == Blocks.wool && !par1World.isRemote)
{
// Если есть, то превращаем оба блока в воздух (удаляем их)
par1World.setBlockToAir(par2int, par3int, par4int);
par1World.setBlockToAir(par2int, par3int - 1, par4int);
// И оставляем на их месте крипера
EntityCreeper Creeper = new EntityCreeper(par1World);
Creeper.setLocationAndAngles((double)par2int + 0.5D, (double)par3int - 0.95D, (double)par4int + 0.5D, 0.0F, 0.0F);
par1World.spawnEntityInWorld(Creeper);
}
}