Изменение текстуры при определенном NBT

Версия Minecraft
1.7.10

Led

291
3
0
Снова доброго времени суток!
На этот раз вопрос такой: можно ли изменять текстуру итема (накладывать слой) при определенном NBT?

Если конкретно:
Я хочу создать несколько модификаторов для инструментов (По аналогии с модификаторами в TF2). Допустим у меня есть кирка (не важно моя или ванильная) я хочу к ней прикрутить декоративный модификатор (например текстуру кирки, обвитой новогодней гирляндой, или веткой). Модификатор в виде итема как то совмещается с киркой (допустим с помощью крафта) и на выходе мы имеем кирку с той же функциональностью, но другим внешним видом (на нее сверху накладывается текстура модификатора).
Так же возможно создания каких либо счетчиков, например убитых игроков. Счетчки в виде итема совмещается с, например мечом или молотом, у меча (молота) изменяется текстура (куда то на ручку пририсовывается счетчик) и в lore указывается количество игроков, убитых этим мечом.

Так же вопрос по расширению цветовой линейки в майнкрафте. Если я хочу добавить помимо стандартных цветов свой цвет, а желательно вообще использовать html цвета по коды, как можно это реализовать?

Заранее благодарен за ответ, он очень интересует.
 
Решение
Использовать getRenderPasses(int metadata) и возвращать количество сколько слоёв IIcon будет в предмете.
Код:
public class ItemItemsCookery extends Item {

	private IIcon
	itemIcon1,
	itemIcon2,
	itemIcon3
	;

	@SideOnly(Side.CLIENT)
	@Override
	public boolean requiresMultipleRenderPasses() {
		return true;
	}

	@Override
	public int getRenderPasses(int metadata) {
		return 4;
	}

	@Override
	public IIcon getIcon(ItemStack is, int pass) {
		switch(pass) {
		case 0: return itemIcon;
		case 1: return itemIcon1;
		case 2: return itemIcon2;
		case 3: return itemIcon3;
		default: return super.getIcon(is, pass);
		}
	}

	@SideOnly(Side.CLIENT)
	@Override
	public void...

timaxa007

Модератор
5,831
409
672
Led написал(а):
На этот раз вопрос такой: можно ли изменять текстуру итема (накладывать слой) при определенном NBT?
Можно. К примеру использовать getIcon(ItemStack stack, int pass) в предмете.

Led написал(а):
на нее сверху накладывается текстура модификатора
Пример можно взять у яйца спавна (не куриное яйцо).

Led написал(а):
Так же возможно создания каких либо счетчиков, например убитых игроков. Счетчки в виде итема совмещается с, например мечом или молотом, у меча (молота) изменяется текстура (куда то на ручку пририсовывается счетчик) и в lore указывается количество игроков, убитых этим мечом.
Эвент на убийство и записывать в NBT (я на подобное отвечал).

Led написал(а):
Так же вопрос по расширению цветовой линейки в майнкрафте. Если я хочу добавить помимо стандартных цветов свой цвет, а желательно вообще использовать html цвета по коды, как можно это реализовать?
Этих линеек много. Если ты про цвет в чате или в описании предмета, то возможно использовать ASM. Добавить в правило чтобы он обрабатывал цвета от HTML и рендерил нужный цвет. Я понятия не имею, как это надо сделать правельно.
 

timaxa007

Модератор
5,831
409
672
Сделать условие на аргумент pass - это второй аргумент в методе. Вот верхним или нижнем я не помню какое условие надо.


Led написал(а):
Вроде можешь.
 

Led

291
3
0
timaxa007 написал(а):
Сделать условие на аргумент pass - это второй аргумент в методе. Вот верхним или нижнем я не помню какое условие надо.


Led написал(а):
Вроде можешь.



Честно говоря, ничего не понял...
Если вы направите меня, буду благодарен.
 

timaxa007

Модератор
5,831
409
672
Использовать getRenderPasses(int metadata) и возвращать количество сколько слоёв IIcon будет в предмете.
Код:
public class ItemItemsCookery extends Item {

	private IIcon
	itemIcon1,
	itemIcon2,
	itemIcon3
	;

	@SideOnly(Side.CLIENT)
	@Override
	public boolean requiresMultipleRenderPasses() {
		return true;
	}

	@Override
	public int getRenderPasses(int metadata) {
		return 4;
	}

	@Override
	public IIcon getIcon(ItemStack is, int pass) {
		switch(pass) {
		case 0: return itemIcon;
		case 1: return itemIcon1;
		case 2: return itemIcon2;
		case 3: return itemIcon3;
		default: return super.getIcon(is, pass);
		}
	}

	@SideOnly(Side.CLIENT)
	@Override
	public void registerIcons(IIconRegister ir) {
		itemIcon = ir.registerIcon(this.getIconString());
		itemIcon1 = ir.registerIcon(this.getIconString() + "1");
		itemIcon2 = ir.registerIcon(this.getIconString() + "2");
		itemIcon3 = ir.registerIcon(this.getIconString() + "3");
	}

}
 

Led

291
3
0
Итак, пытался добавлять слой при определенном NBT.
Но столкнулся с проблемой, что я мне нужно получить itemStack в registerIcons.
Вообщем смысл в том, что я хочу, если NBT != 0, накладывать еще один слой, itemIconModificator, и в зависимости от NBT менять текстуру этого слоя.

Код:
package ru.legendary.lwmod.lwmtool.item;

import java.util.List;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import ru.legendary.lwmod.lwmtool.LWMTool;
import ru.legendary.lwmod.lwmtool.core.ModCreativeTabs;
import ru.legendary.lwmod.lwmtool.core.ModMaterials;

public class itemLWMPickaxe extends ItemPickaxe  
{
 private int handle;
    private IIcon theIcon;
    private int material;
    
    private IIcon itemIconHead, itemIconModificator;
    
 /**
 * 
 * @param Name Имя итема, по нему итем получает нелокализованное имя
 * @param ToolMaterial Материал, по нему получает свойства материала
 * @param Handle число, описывающее ручку (для отрисовки) 0 - деревянная, 1 - железо, 2 - алм, 3 - кристалл
 * @param Material число, описывающее обух (для отрисовки) 0 - железо, 1 - алмаз, 2 кристалл, 3 - метролиум
 */
 public itemLWMPickaxe(String Name, ToolMaterial ToolMaterial, int Handle, int Material) 
 {
 super(ToolMaterial);
 this.handle = Handle;
 this.material = Material;
        this.setUnlocalizedName(LWMTool.MOD_ID + "." + Name);
        this.setCreativeTab(ModCreativeTabs.tabLWMTool);
        switch(Handle) //текстура ручки
        {
         case 1: this.setTextureName(LWMTool.MOD_ID + ":ironHandlePickAxe");break; //железо
         case 2: this.setTextureName(LWMTool.MOD_ID + ":diamondHandlePickAxe");break; //алмаз
         case 3: this.setTextureName(LWMTool.MOD_ID + ":crystalHandlePickAxe");break; //кристалл
         default: this.setTextureName(LWMTool.MOD_ID + ":woodHandlePickAxe");break; //дерево (по дефолту)
        }
 }
 
 /**
 * А тут добавим информацию о ручке в lore кирки
 */
 @Override
 public void addInformation(ItemStack ItemStack, EntityPlayer EntityPlayer, List List, boolean bool)
 {
 if (ItemStack.stackTagCompound != null) {
       String modificator = ItemStack.stackTagCompound.getString("modificator"); 
       List.add("Modificator " + modificator);
 
 }
        switch(this.handle)
        {
         case 1: List.add(StatCollector.translateToLocal("lore.legendarymod.handle.iron"));break; //железо
         case 2: List.add(StatCollector.translateToLocal("lore.legendarymod.handle.diamond"));break; //алмаз
         case 3: List.add(StatCollector.translateToLocal("lore.legendarymod.handle.crystal"));break; //кристалл
         //дерево (по дефолту)
        }
 }
 /**
 * Попытаемся создать NBT для проверки на наличие модификатора
 */
 public void onCreated(ItemStack ItemStack, World World, EntityPlayer Player) 
 {
 ItemStack.stackTagCompound = new NBTTagCompound();
 ItemStack.stackTagCompound.setInteger("modificator", 0);//);("modificator", Player.getDisplayName()); 
 }
 
 /**
 * Тут включим возможность наложения текстур
 */
 @SideOnly(Side.CLIENT)
 public boolean requiresMultipleRenderPasses()
 {
    return true;
 }
 
    /**
     * Вернуть общее количество текстура количество слоев + 1
     */
    @Override
    public int getRenderPasses(int Meta) 
    {
        return 2;
    }

    /**
     * Привяжем текстуры к каждому pass
     */
    @Override
    public IIcon getIcon(ItemStack ItemStack, int Pass) 
    {
     
        switch(Pass) 
        {
         case 0: return itemIcon;
         case 1: return itemIconHead;
         case 2: return itemIconModificator;
         //case 3: return itemIcon3;
         //case 4: return itemIcon4;
         default: return super.getIcon(ItemStack, Pass);
        }
    }
    /**
     * Наложем все текстуры
     */
    @SideOnly(Side.CLIENT)
    @Override
    public void registerIcons(IIconRegister ir) 
    {
 String s;
     //Выберем иконку для наболдашника
 switch(this.material)
 {
       case 1: s = ":diamondPickaxeHead"; break; //алмаз
       case 2: s = ":crystalPickaxeHead"; break; //кристалл
       case 3: s = ":metroliumPickaxeHead"; break; //метроллиум
       default: s =":ironPickaxeHead"; break; //железо (по умолчанию)
       }

     //Выберем модификатор ///ОТКУДА ВЗЯТЬ IS?
 /*
 String m;
 NBTTagCompound nbt = this.getTagCompound();
 switch()
 {
 
 
 }
 */
        itemIcon = ir.registerIcon(this.getIconString());
        itemIconHead = ir.registerIcon(LWMTool.MOD_ID + s);
        itemIconModificator = ir.registerIcon(this.getIconString() + "_NY");
        //itemIcon3 = ir.registerIcon(this.getIconString() + "3");
        //itemIcon4 = ir.registerIcon(this.getIconString() + "4");
    }
}
 

timaxa007

Модератор
5,831
409
672
Led, как именно в крафт-столе, если тебе конечно нужно чтобы проверять NBT в сетке крафта, я ещё не научился, но знаю что для этого нужно создать класс с присоединить интерфейс net.minecraft.item.crafting.IRecipe. А если тебе только на выходе, то просто в результат рецепта даёшь NBT.
 

Led

291
3
0
Мне нужно проверять, наверное.
То есть при крафте, допустим кирки с определенным итемом, мы получаем кирку с NBT 1 при условии у кирки в рецепте NBT 0 или null


Еще вопрос, что ответственно за порядок наложения текстур?
У меня получается так, что при NBT 1 порядок один, при NBT null порядок другой?
(Внимание на соединение набалдашника и рукоятки)
T4-2DPoTVT0.jpg

vca-i4IGSII.jpg

Код:
package ru.legendary.lwmod.lwmtool.item;

import java.util.List;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import ru.legendary.lwmod.lwmtool.LWMTool;
import ru.legendary.lwmod.lwmtool.core.ModCreativeTabs;
import ru.legendary.lwmod.lwmtool.core.ModMaterials;

public class itemLWMPickaxe extends ItemPickaxe  
{
 private int handle;
   // private IIcon theIcon;
    private int material;
    
    private IIcon itemIconHead, itemIconMod1, itemIconMod2;
    
 /**
 * @param Name Имя итема, по нему итем получает нелокализованное имя
 * @param ToolMaterial Материал, по нему получает свойства материала
 * @param Handle число, описывающее ручку (для отрисовки) 0 - деревянная, 1 - железо, 2 - алм, 3 - кристалл
 * @param Material число, описывающее обух (для отрисовки) 0 - железо, 1 - алмаз, 2 кристалл, 3 - метролиум
 */
 public itemLWMPickaxe(String Name, ToolMaterial ToolMaterial, int Handle, int Material) 
 {
 super(ToolMaterial);
 this.handle = Handle;
 this.material = Material;
        this.setUnlocalizedName(LWMTool.MOD_ID + "." + Name);
        this.setCreativeTab(ModCreativeTabs.tabLWMTool);
        switch(Handle) //текстура ручки
        {
         case 1: this.setTextureName(LWMTool.MOD_ID + ":ironHandlePickAxe");break; //железо
         case 2: this.setTextureName(LWMTool.MOD_ID + ":diamondHandlePickAxe");break; //алмаз
         case 3: this.setTextureName(LWMTool.MOD_ID + ":crystalHandlePickAxe");break; //кристалл
         default: this.setTextureName(LWMTool.MOD_ID + ":woodHandlePickAxe"); //дерево (по дефолту)
        }
 }
 
 /**
 * А тут добавим информацию о ручке в lore кирки
 */
 @Override
 public void addInformation(ItemStack ItemStack, EntityPlayer EntityPlayer, List List, boolean bool)
 {
 //Добавим информацию о модификаторе
 if (ItemStack.stackTagCompound != null) {
       String modificator = ItemStack.stackTagCompound.getString("modificator"); 
       List.add("Modificator " + modificator);
 
 }
        switch(this.handle)
        {
         case 1: List.add(StatCollector.translateToLocal("lore.legendarymod.handle.iron"));break; //железо
         case 2: List.add(StatCollector.translateToLocal("lore.legendarymod.handle.diamond"));break; //алмаз
         case 3: List.add(StatCollector.translateToLocal("lore.legendarymod.handle.crystal"));break; //кристалл
         //дерево (по дефолту)
        }
 }
 /**
 * Попытаемся создать NBT для проверки на наличие модификатора
 */
 public void onCreated(ItemStack ItemStack, World World, EntityPlayer Player) 
 {
 ItemStack.stackTagCompound = new NBTTagCompound();
 ItemStack.stackTagCompound.setInteger("modificator", 1);
 }
 
 /**
 * Тут включим возможность наложения текстур
 */
 @SideOnly(Side.CLIENT)
 public boolean requiresMultipleRenderPasses()
 {
    return true;
 }
 
    /**
     * Вернуть общее количество текстура количество слоев + 1
     */
    @Override
    public int getRenderPasses(int Meta) 
    {
        return 3;
    }
    /**
     * Зарегистрируем текстуры все текстуры
     */
    @SideOnly(Side.CLIENT)
    @Override
    public void registerIcons(IIconRegister ir) 
    {
 String s;
     //Выберем иконку для наболдашника
 switch(this.material)
 {
       case 1: s = ":diamondPickaxeHead"; break; //алмаз
       case 2: s = ":crystalPickaxeHead"; break; //кристалл
       case 3: s = ":metroliumPickaxeHead"; break; //метроллиум
       default: s =":ironPickaxeHead"; break; //железо (по умолчанию)
       }
 
        itemIconHead = ir.registerIcon(LWMTool.MOD_ID + s);
        itemIcon = ir.registerIcon(this.getIconString());
        itemIconMod1 = ir.registerIcon(LWMTool.MOD_ID + ":modPickaxe1");
        itemIconMod2 = ir.registerIcon(LWMTool.MOD_ID + ":modPickaxe2");
    }

    /**
     * Выдадим текстуру
     */
    @Override
    public IIcon getIcon(ItemStack ItemStack, int Pass) 
    {
     IIcon s = null;
 if (ItemStack.stackTagCompound != null)
 {
 int modificator = ItemStack.stackTagCompound.getInteger("modificator");
 switch(modificator)
 {
 case 1: s = itemIconMod1; break;
 case 2: s = itemIconMod2; break;
 }
     }
     
        switch(Pass) 
        {
         case 0: return itemIcon;
         case 1: return itemIconHead;
         case 2: if(s != null) return s;
         default: return super.getIcon(ItemStack, Pass);
        }
    }
}
 

timaxa007

Модератор
5,831
409
672
Led написал(а):
Еще вопрос, что ответственно за порядок наложения текстур?
Аргумент pass, чем больше его значение, тем выше этот слой.
 

Led

291
3
0
Пробовал. Почему то слой, определяемый .setTextureName() выше всех.
Заметьте, что при NBT 1 все впорядке, а без него нет.

Еще раз приведу фрагмент кода
Код:
       switch(Pass) 
        {
         case 0: return itemIcon;
         case 1: return itemIconHead;
         case 2: if(s != null) return s;
         default: return super.getIcon(ItemStack, Pass);
        }

itemIcon (текстура ручки) самый нижний слой, но он является таковым только при именном NBT, в противном случае (без NBT) он становится самым верхним.

Как я понял методом тыка, при пустом case 2, case 0 вообще игнорируется, сразу же идет case 1.

Очень прошу помочь!

_____________
Как я понял, косяки с отображением возникают тогда, когда количество слоев в getRenderPasses(int Meta) не соответствует реальному количеству слоев. То есть если какой то слой пропущен (ну ненужен он), то порядок наложения едет. Конечно, можно сделать прозрачную текстуру и накладывать ее, но не хочу писать костыли. Резонный вопрос, как в getIcon(ItemStack ItemStack, int Pass) правильно пропускать текстуру?
_____________
В качестве временного решения возвращаю еще раз текстуру верхушки кирки, что не очень приемлемо, но работает.

Код:
    */
    @Override
    public IIcon getIcon(ItemStack ItemStack, int Pass) 
    {
     int t = 1;
     IIcon s = null;
 if (ItemStack.stackTagCompound != null)
 {
 int modificator = ItemStack.stackTagCompound.getInteger("modificator");
 switch(modificator)
 {
 case 1: s = itemIconMod1; break;
 case 2: s = itemIconMod2;
 }
     }
     
        switch(Pass) 
        {
         case 0: return itemIcon;
         case 1: return itemIconHead;
         case 2: if(s != null) return s; else return itemIconHead;// break;
         default: return super.getIcon(ItemStack, Pass); //вернем иконку по стандарту
        }
    }
 
Сверху