А теперь немного уникальности!
Начнем!
Пишем в load регистрацию рендера предмета
MinecraftForgeClient.registerItemRenderer(TutModCore.TutItem.itemID, new ItemRenderTutItem());
TutModCore.TutItem.itemID - какой предмет будем рендерить
new ItemRenderTutItem() - какой рендер будем использовать(класс)
Жмем ctrl+o+shift
Создаем класс ItemRenderTutItem
package ru.tutmod.src;
import org.lwjgl.opengl.GL11;
import ru.tutmod.src.ModelTutItem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainerCreative;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.IItemRenderer;
public class ItemRenderTutItem
implements IItemRenderer
{
protected ModelTutItem tutitemModel;
public ItemRenderTutItem()
{
tutitemModel = new ModelTutItem();
}
@Override
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
switch(type)
{
case EQUIPPED: return true;
default: return false;
}
}
@Override
public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item,
ItemRendererHelper helper) {
return false;
}
@Override
public void renderItem(ItemRenderType type, ItemStack item, Object... data)
{
switch(type)
{
case EQUIPPED:
{
GL11.glPushMatrix();
GL11.glRotatef(180F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(0F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-45F, 0.0F, 0.0F, 1.0F);
boolean isFirstPerson = false;
if(data[1] !=null & data[1] instanceof EntityPlayer)
{
if(!((EntityPlayer)data[1] == Minecraft.getMinecraft().renderViewEntity && Minecraft.getMinecraft().gameSettings.thirdPersonView == 0 && !((Minecraft.getMinecraft().currentScreen instanceof GuiInventory || Minecraft.getMinecraft().currentScreen instanceof GuiContainerCreative) && RenderManager.instance.playerViewY == 180.0F)))
{
GL11.glTranslatef(0.75F, -1F, 0F);
}
else
{
isFirstPerson = true;
GL11.glTranslatef(0.8F, -0.8F, 0.2F);
}
}
else
{
GL11.glTranslatef(0.65F, -1.2F, 0F);
}
float scale = 0.8F;
GL11.glScalef(scale, scale, scale);
Minecraft.getMinecraft().renderEngine.bindTexture("/mods/TutMod/textures/tutitem.png");
icewandModel.render((Entity)data[1], 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0625F);
GL11.glPopMatrix();
}
default:
break;
}
}
}
Сейчас разберем и немного нагрузим ваш мозг координатными осями
x, y, z protected ModelTutItem tutitemModel;
public ItemRenderTutItem()
{
tutitemModel = new ModelTutItem();
}
Наша модель ModelTutItem (дальше разберем) будет использовать строку tutitemModel в классе рендера
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
switch(type)
{
case EQUIPPED: return true;
default: return false;
}
}
Тип рендера
А теперь сам рендер
public void renderItem(ItemRenderType type, ItemStack item, Object... data)
{
switch(type)
{
case EQUIPPED:
{
GL11.glPushMatrix();
GL11.glRotatef(180F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(0F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-45F, 0.0F, 0.0F, 1.0F);
boolean isFirstPerson = false;
if(data[1] !=null & data[1] instanceof EntityPlayer)
{
if(!((EntityPlayer)data[1] == Minecraft.getMinecraft().renderViewEntity && Minecraft.getMinecraft().gameSettings.thirdPersonView == 0 && !((Minecraft.getMinecraft().currentScreen instanceof GuiInventory || Minecraft.getMinecraft().currentScreen instanceof GuiContainerCreative) && RenderManager.instance.playerViewY == 180.0F)))
{
GL11.glTranslatef(0.75F, -1F, 0F);
}
else
{
isFirstPerson = true;
GL11.glTranslatef(0.8F, -0.8F, 0.2F);
}
}
else
{
GL11.glTranslatef(0.65F, -1.2F, 0F);
}
float scale = 0.8F;
GL11.glScalef(scale, scale, scale);
Minecraft.getMinecraft().renderEngine.bindTexture("/mods/TutMod/textures/tutitem.png");
icewandModel.render((Entity)data[1], 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0625F);
GL11.glPopMatrix();
}
default:
break;
}
}
GL11.glRotatef(180F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(0F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-45F, 0.0F, 0.0F, 1.0F);
Вращение модели по осям (в каждой строке 1.0F означает ось x y или z и мощность поворота). С этим экспериментируйте.
boolean isFirstPerson = false;
if(data[1] !=null & data[1] instanceof EntityPlayer)
{
if(!((EntityPlayer)data[1] == Minecraft.getMinecraft().renderViewEntity && Minecraft.getMinecraft().gameSettings.thirdPersonView == 0 && !((Minecraft.getMinecraft().currentScreen instanceof GuiInventory || Minecraft.getMinecraft().currentScreen instanceof GuiContainerCreative) && RenderManager.instance.playerViewY == 180.0F)))
{
GL11.glTranslatef(0.75F, -1F, 0F);
}
else
{
isFirstPerson = true;
GL11.glTranslatef(0.8F, -0.8F, 0.2F);
}
}
else
{
GL11.glTranslatef(0.65F, -1.2F, 0F);
}
Проверка вида от 1 лица(рендериться от 1 лица и от 3 будет по разному)
GL11.glTranslatef(0.75F, -1F, 0F); - смещение по осям при виде от 3 лица
isFirstPerson = true;
GL11.glTranslatef(0.8F, -0.8F, 0.2F); - смещение по осям при виде от 1 лица
float scale = 0.8F;
GL11.glScalef(scale, scale, scale); - изменяет размер модели (размер какой был при создании модели - 1.0F)
И последнее - текстура
Minecraft.getMinecraft().renderEngine.bindTexture("/mods/TutMod/textures/tutitem.png");
Думаю тут все понятно
Так теперь нам нужна модель. И тут время творчества!
Качаем Techne
отсюдаДелаем модельку
Внимание!Поля в Position должны быть равны нулю!
Двигаем части модели только Offset!
Это правило только для модели итема
Задняя часть модели - R (можно посмотреть в правом нижнем углу в Techne)делаем класс ModelTutItem
package rututmod.src;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
public class ModelTutItem extends ModelBase
{
}
я сделал модель из 2 частей(все части должны называться по разному) и techne дал мне такой код
// Date: 17.06.2013 13:48:45
// Template version 1.1
// Java generated by Techne
// Keep in mind that you still need to fill in some blanks
// - ZeuX
package net.minecraft.src;
public class ModelNew extends ModelBase
{
//fields
ModelRenderer Shape1;
ModelRenderer Shape2;
public ModelNew()
{
textureWidth = 64;
textureHeight = 32;
Shape1 = new ModelRenderer(this, 0, 0);
Shape1.addBox(0F, 0F, 0F, 1, 23, 1);
Shape1.setRotationPoint(0F, 0F, 0F);
Shape1.setTextureSize(64, 32);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 0);
Shape2.addBox(7F, 16F, 0F, 5, 1, 1);
Shape2.setRotationPoint(0F, 0F, 0F);
Shape2.setTextureSize(64, 32);
Shape2.mirror = true;
setRotation(Shape2, 0F, 0F, 0.3490659F);
}
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);
}
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);
}
}
Вставляем только
//fields
ModelRenderer Shape1;
ModelRenderer Shape2;
public ModelNew()
{
textureWidth = 64;
textureHeight = 32;
Shape1 = new ModelRenderer(this, 0, 0);
Shape1.addBox(0F, 0F, 0F, 1, 23, 1);
Shape1.setRotationPoint(0F, 0F, 0F);
Shape1.setTextureSize(64, 32);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 0);
Shape2.addBox(7F, 16F, 0F, 5, 1, 1);
Shape2.setRotationPoint(0F, 0F, 0F);
Shape2.setTextureSize(64, 32);
Shape2.mirror = true;
setRotation(Shape2, 0F, 0F, 0.3490659F);
}
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);
}
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 ModelNew() меняем на public ModelTutItem()
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);
}
Тут добавляем в
setRotationAngles(f, f1, f2, f3, f4, f5); после f5 это
, entity public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity ent)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5, ent);
}
Тут в
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5) добавляем после f5 это
, Entity entИ в
super.setRotationAngles(f, f1, f2, f3, f4, f5); добавляем после f5 это
, entА рзобрать здесь нужно только это
textureWidth = 64;
textureHeight = 32;
Это размеры текстур.
Все с вращением и смещением экспериментируйте. Удачи!
Ore Dictionary - он же словарь руд - позволяет модам использовать аналогичные руды\материалы\да_что_угодно из других модов. Например, олово из IC2 можно использовать в Forestry. Очень удобный инструмент. Давайте, для примера, добавим туда наш предмет, как медный слиток. Для этого достаточно добавить одну строку в void load():
OreDictionary.registerOre("ingotCopper", TutItem);
Первый аргумент - строковой идентификатор, второй - собственно, предмет\блок. Обычно строковые идентификаторы задают именно такие: тип_предметаМатериал. То есть, ingotCopper, oreTin, ingotSilver и так далее. Вы можете задать любой, но вряд ли тогда это будет работать.
Использовать Ore Dictionary в рецептах нужно так(крафтим землю):
GameRegistry.addRecipe(new ItemStack(Block.dirt, 1), new Object[]{
"#X#",
"#X#",
"#X#",
Character.valueOf('X'), Block.cobblestone, Character.valueOf('#'), "ingotCopper"});
Всем привет и сейчас ты будешь делать ступеньки!
Начнем!
Регистрируем блок ступенек
public static Block TutStairs;
Регистрируем в load
TutStairs = new TutStairs(TutStairsID, Block.bedrock, 0).setLightOpacity(0).setHardness(1.5F).setResistance(3.5F).setUnlocalizedName("Bed Rock Stairs");
GameRegistry.registerBlock(TutStairs, "Tutorial.TutStairs");
LanguageRegistry.addName(TutStairs, "Tutorial Stairs");
Вместо bedrock может быть любой другой блок.
Делаем класс TutStairs
package ru.tutmod.src;
import net.minecraft.block.Block;
import net.minecraft.block.BlockStairs;
public class TutStairs extends BlockStairs{
protected TutStairs(int par1, Block par2Block, int par3) {
super(par1, par2Block, par3);
}
}
Например вы сделали хороший мод и решили показать его не только друзьям и российским форумам но и ,например, на форум
minecraftforum.net. Но там русский язык не возьмут а тут не поймут английского! Для этого регистрируем язык -
дефолтный, английский и русскийВозьмем нашу регистрацию языка у TutBlock
LanguageRegistry.addName(TutBlock, "Tutorial Block");
Это будет дефолтное название. Его надо на английском.
А теперь наши локализации под английский и русский
LanguageRegistry.instance().addNameForObject(TutBlock "en_US", "Tutorial Block");
LanguageRegistry.instance().addNameForObject(TutBlock, "ru_RU", "Учебный блок");
Если приглядеться то увидите что тут юзаем
instance().addNameForObjectНу а по сокращениям локализаций (ru_RU и т.д.) можно поискать в файле
languages.txt по пути
minecraft.jar\lang\Значит мы такие сделали блок с моделью, моба или что-либо с рендером.
Но сервер на нас ругается! Что делать? Поможет прокси!
Начнем!
В главном файле после
public class TutModCore {
Пишем
@SidedProxy(clientSide = "ru.tutmod.src.ClientProxy", serverSide = "ru.tutmod.src.CommonProxy")
public static CommonProxy proxy;
Объяснью
clientSide = "ru.tutmod.src.ClientProxy", serverSide = "ru.tutmod.src.CommonProxy"
Это у нас где лежат прокси
public static CommonProxy proxy;
Это у нас сама прокси
Теперь в лоад
proxy.initMod();
Это у нас то, куда пишем рендер.
Теперь создаем файлы
CommonProxy и
ClientProxyCommonProxypackage ru.tutmod.src;
public class CommonProxy
{
public void initMod()
{
}
}
ClientProxypackage ru.tutmod.src;
public class ClientProxy extends CommonProxy
{
@Override
public void initMod()
{
super.initMod();
}
}
Дальше мы будем делать моба и вы увидите как использовать прокси.
З.Ы.РЕНДЕРЫ ПИШЕМ ТОЛЬКО В ClientProxy ПОСЛЕ super.initMod();