Степени, заборы, калитка и д.р. - всё это модели блоков. Сегодня мы научимся вставлять наши модели из Techne в Minecraft.
Всё, что нам нужно:
JDK | Стандартный набор разработчика |
Eclipse | Для удобной работы с исходниками игры |
MCP (любой, но в нашем случае 1.4.6) | Поможет декомпилировать исходники |
Techne | Работа с моделями |
Forge src | библиотека forge |
Я не буду рассказывать, как создать файл мода Это есть на любом сайте.
После установки всего этого мы можем спокойно писать моды на Forge.
Чтобы добавить блоку модель, нужно пройти операций:
Класс блока, BlockHandler, BlockModel, Renderer, TileEntity.
Научимся вставлять нашу модель в игру на примере лестницы.
В классе нашего мода пишем:
public static int renderLadderModelID;//это будет наш RenderType
public static Block ladderModel = new LadderBlock(2024).setCreativeTab(CreativeTabs.tabBlock).setHardness(0.0F).setBlockName("LadderModel");
После
public void load(FMLInitializationEvent event)
{
Пишем:
GameRegistry.registerBlock(ladderModel);
GameRegistry.registerTileEntity( testmod.TileEntityLadderModel.class, "TileEntityLadderModel" );
LanguageRegistry.addName(ladderModel, "Лестница");
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityLadderModel.class, new RendererLadderModel());//регистрируем рендер, и энтити
//это поможет нам отрендерить модель в руке, то-есть как сундук
renderLadderModelID = RenderingRegistry.getNextAvailableRenderId();
RenderingRegistry.registerBlockHandler(renderLadderModelID, new LadderBlockHandler());
Переходим к созданию блока и добавлении модели.
Создаем класс LadderBlock.java и туда пишем:
package testmod;
import static net.minecraftforge.common.ForgeDirection.EAST;
import static net.minecraftforge.common.ForgeDirection.NORTH;
import static net.minecraftforge.common.ForgeDirection.SOUTH;
import static net.minecraftforge.common.ForgeDirection.WEST;
import java.util.Random;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.*;
public class LadderBlock extends BlockContainer
{
public LadderBlock(int id)
{
super(id, Material.circuits);
}
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
{
this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
}
@SideOnly(Side.CLIENT)
public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{
this.updateLadderBounds(par1IBlockAccess.getBlockMetadata(par2, par3, par4));
}
public void updateLadderBounds(int par1)
{
float var3 = 0.125F;
if (par1 == 2)
{
this.setBlockBounds(0.0F, 0.0F, 1.0F - var3, 1.0F, 1.0F, 1.0F);
}
if (par1 == 3)
{
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var3);
}
if (par1 == 4)
{
this.setBlockBounds(1.0F - var3, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
}
if (par1 == 5)
{
this.setBlockBounds(0.0F, 0.0F, 0.0F, var3, 1.0F, 1.0F);
}
}
public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
{
return par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST ) ||
par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST ) ||
par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) ||
par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH);
}
public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
{
this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
return super.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4);
}
public int getRenderType()
{
return TestModBase.renderLadderModelID;//выбираем наш рендер
}
public boolean isOpaqueCube()
{
return false;
}
public boolean renderAsNormalBlock()
{
return false;
}
public int func_85104_a(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
{
int var10 = par9;
if ((var10 == 0 || par5 == 2) && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
{
var10 = 2;
}
if ((var10 == 0 || par5 == 3) && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
{
var10 = 3;
}
if ((var10 == 0 || par5 == 4) && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
{
var10 = 4;
}
if ((var10 == 0 || par5 == 5) && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST))
{
var10 = 5;
}
return var10;
}
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
{
int var6 = par1World.getBlockMetadata(par2, par3, par4);
boolean var7 = false;
if (var6 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
{
var7 = true;
}
if (var6 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
{
var7 = true;
}
if (var6 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
{
var7 = true;
}
if (var6 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST))
{
var7 = true;
}
if (!var7)
{
this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
par1World.setBlockWithNotify(par2, par3, par4, 0);
}
super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
}
public void setBlockBoundsForItemRender()
{
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.25F);
}
public int quantityDropped(Random par1Random)
{
return 1;
}
@Override
public boolean isLadder(World world, int x, int y, int z)
{
return true;
}
@Override
public TileEntity createNewTileEntity(World world)
{
return new TileEntityLadderModel();
}
}
В основном тут идет ссылка на размер рендера, возможность подниматься по лестнице и поворот на стороны света. Здесь сработает только рендер и возможность подниматься.
Готово.
Теперь создаем TileEntityLadderModel, в который вставляем:
package testmod;
import net.minecraft.tileentity.TileEntity;
public class TileEntityLadderModel extends TileEntity
{
public TileEntityLadderModel()
{
}
}
Теперь непосредственно можно переходить к модели нашей лестницы.
При создании и экспорте модели из Techne в Java, ан выходе получаем код:
package net.minecraft.src;
public class Modelladder extends ModelBase
{
//fields
ModelRenderer Shape1;
ModelRenderer Shape2;
ModelRenderer Shape3;
ModelRenderer Shape4;
ModelRenderer Shape5;
ModelRenderer Shape6;
public Modelladder()
{
textureWidth = 32;
textureHeight = 32;
Shape1 = new ModelRenderer(this, 0, 0);
Shape1.addBox(0F, 0F, 0F, 2, 16, 2);
Shape1.setRotationPoint(-8F, 8F, 5F);
Shape1.setTextureSize(32, 32);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 0);
Shape2.addBox(0F, 0F, 0F, 2, 16, 2);
Shape2.setRotationPoint(-8F, 8F, -7F);
Shape2.setTextureSize(32, 32);
Shape2.mirror = true;
setRotation(Shape2, 0F, 0F, 0F);
Shape3 = new ModelRenderer(this, 0, 0);
Shape3.addBox(0F, 0F, 0F, 1, 2, 16);
Shape3.setRotationPoint(-8F, 9F, -8F);
Shape3.setTextureSize(32, 32);
Shape3.mirror = true;
setRotation(Shape3, 0F, 0F, 0F);
Shape4 = new ModelRenderer(this, 0, 0);
Shape4.addBox(0F, 0F, 0F, 1, 2, 16);
Shape4.setRotationPoint(-8F, 13F, -8F);
Shape4.setTextureSize(32, 32);
Shape4.mirror = true;
setRotation(Shape4, 0F, 0F, 0F);
Shape5 = new ModelRenderer(this, 0, 0);
Shape5.addBox(0F, 0F, 0F, 1, 2, 16);
Shape5.setRotationPoint(-8F, 17F, -8F);
Shape5.setTextureSize(32, 32);
Shape5.mirror = true;
setRotation(Shape5, 0F, 0F, 0F);
Shape6 = new ModelRenderer(this, 0, 0);
Shape6.addBox(0F, 0F, 0F, 1, 2, 16);
Shape6.setRotationPoint(-8F, 21F, -8F);
Shape6.setTextureSize(32, 32);
Shape6.mirror = true;
setRotation(Shape6, 0F, 0F, 0F);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5);
Shape1.render(f5);
Shape2.render(f5);
Shape3.render(f5);
Shape4.render(f5);
Shape5.render(f5);
Shape6.render(f5);
}
private void setRotation(ModelRenderer model, float x, float y, float z)
{
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5);
}
}
public void render()
{
Shape1.render(0.0625F);
Shape2.render(0.0625F);
Shape3.render(0.0625F);
Shape4.render(0.0625F);
Shape5.render(0.0625F);
Shape6.render(0.0625F);
}
Далее создаем класс RendererLadderModel и в него вставляем:
package testmod;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.tileentity.*;
import net.minecraft.tileentity.TileEntity;
public class RendererLadderModel extends TileEntitySpecialRenderer
{
private static ModelLadder model;//наша модель
public RendererLadderModel()
{
model = new ModelLadder();
}
public void renderTileEntityAt(TileEntity tileEntity, double d1, double d2, double d3, float f)
{
this.renderTileEntity((TileEntityLadderModel)tileEntity, d1, d2, d3, f);
}
public void renderTileEntity(TileEntityLadderModel tileEntity, double d1, double d2, double d3, float f)
{
GL11.glPushMatrix();
GL11.glTranslatef((float)d1 + 0.5F, (float)d2 + 1.5F, (float)d3 + 0.5F);
GL11.glRotatef(180F, 0.0F, 0.0F, 1.0F);
this.bindTextureByName("/testmod/models/wood.png");//текстура
this.model.render();
GL11.glPopMatrix();
}
}
Здесь мы выбираем модель блока, TileEntity и присваиваем текстуру.
И теперь всё, что нам осталось - добавить класс LadderBlockHandler, в который мы вставляем:
package testmod;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.world.IBlockAccess;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
public class LadderBlockHandler implements ISimpleBlockRenderingHandler
{
@Override
public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer)
{
if(block == TestModBase.ladderModel) //Выбираем модель
TileEntityRenderer.instance.renderTileEntityAt(new TileEntityLadderModel(), 0D, 0D, 0D, 0F);
}
@Override
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer)
{
return false;
}
@Override
public boolean shouldRender3DInInventory() //Надо ли рендерить блок в инвентаре
{
return true;
}
@Override
public int getRenderId()
{
return 0;
}
}
Готово. Наша лестница появилась в игре!