Окрас текстуры предмета

Версия Minecraft
1.7.10
API
Forge
192
2
9
Всем доброго времени суток!
Не могу понять в чем дело... Хотел покрасить текстуру и покрасил, работает!
Но теперь нужно чуточку усложнить и покрасить конкретный слой в этой текстуре, а как это сделать, не соображаю:(

Полез смотреть броник и яйца, но в обоих случаях так и не понял, где прячется логика окраса конкретного слоя.
Скопипастил код с ваниллки, у меня красятся сразу все слои. Куда копать?)

P.S. Пытался сделать универсальный класс для создания предмета с сабайди или без, так что не ужасайтесь:D

ItemBase:
package mod.test.item;

import java.util.List;

import mod.test.Vars;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemDye;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;

public class ItemBase extends Item {
    
    @SideOnly(Side.CLIENT)
    private IIcon[] icons;
    
    private int[] colors;
    private String[] names;
    
    public ItemBase(String[] names, int stack, int[] colors) {
        this.setUnlocalizedName(names[0]);
        this.setTextureName(Vars.MODID + ":" + names[0]);
        this.setMaxStackSize(stack);
        this.setCreativeTab(Vars.TAB);
        this.colors = colors;
        this.names = names;
        if (names.length > 1 || colors.length > 0) this.setHasSubtypes(true);
    }
    
    public ItemBase(String name, int stack, int[] colors) {
        this(new String[] { name }, stack, colors);
    }
    
    public ItemBase(String name) {
        this(new String[] { name }, 1, new int[] {});
    }
    
    public ItemBase(String[] names) {
        this(names, 1, new int[] {});
    }
    
    public ItemBase(String name, int[] colors) {
        this(new String[] { name }, 1, colors);
    }
    
    public ItemBase(String[] names, int[] colors) {
        this(names, 1, colors);
    }
    
    public ItemBase(String name, int stack) {
        this(new String[] { name }, stack, new int[] {});
    }
    
    public ItemBase(String[] names, int stack) {
        this(names, stack, new int[] {});
    }
    
    @Override
    public String getUnlocalizedName(ItemStack stack) {
        return "item." + (names.length < stack.getItemDamage() ? names[0] : names[0] + "_" + names[stack.getItemDamage()+1]);
    }
    
    @SideOnly(Side.CLIENT)
    public boolean requiresMultipleRenderPasses() {
        return true;
    }
    
    @SideOnly(Side.CLIENT)
    public IIcon getIconFromDamageForRenderPass(int meta, int rPass) {
        return rPass > 0 ? super.getIconFromDamageForRenderPass(meta, rPass) : icons[1];
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void registerIcons(IIconRegister reg) {
        super.registerIcons(reg);
        
        icons = new IIcon[colors.length > 0 ? 2 : names.length];
        if (colors.length > 0) {
            icons[0] = reg.registerIcon(Vars.MODID + ":" + names[0]);
            icons[1] = reg.registerIcon(Vars.MODID + ":" + names[0] + "_overlay");
            return;
        }
        
        for (int i = 1; i < names.length; i++)
            icons[i-1] = reg.registerIcon(Vars.MODID + ":" + names[0] + "_" + names[i]);
    }

    @Override
    @SideOnly(Side.CLIENT)
    public int getColorFromItemStack(ItemStack stack, int renderPass) {
        return colors.length == 0 ? 0xFFFFFF : colors[stack.getItemDamage()];
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void getSubItems(Item item, CreativeTabs tab, List items) {
        if (colors.length == 0 && names.length < 2) return;
        for (int dmg = 0, size = colors.length == 0 ? names.length-1 : colors.length; dmg < size; dmg++)
            items.add(new ItemStack(item, 1, dmg));
    }
    
}
 
Решение
Java:
public class FooItem extends Item {
    @SideOnly(Side.CLIENT)
    private IIcon theIcon;

   public FooItem() {
       this.setHasSubtypes(true);
   }

    /**
    * Returns the color of the item based on its damage and the render pass.
    */
    @SideOnly(Side.CLIENT)
    public int getColorFromItemStack(ItemStack stack, int renderPass) {
        EntityList.EntityEggInfo entityegginfo = (EntityList.EntityEggInfo)EntityList.entityEggs.get(Integer.valueOf(stack.getMetadata()));
        return (eggInfo != null) ? (renderPass == 0 ? eggInfo.primaryColor : eggInfo.secondaryColor) : 16777215;
    }
   
    /**  
    * Returns true if this item requires multiple render passes.
    */
    @SideOnly(Side.CLIENT)
    public boolean...
173
13
25
Java:
public class FooItem extends Item {
    @SideOnly(Side.CLIENT)
    private IIcon theIcon;

   public FooItem() {
       this.setHasSubtypes(true);
   }

    /**
    * Returns the color of the item based on its damage and the render pass.
    */
    @SideOnly(Side.CLIENT)
    public int getColorFromItemStack(ItemStack stack, int renderPass) {
        EntityList.EntityEggInfo entityegginfo = (EntityList.EntityEggInfo)EntityList.entityEggs.get(Integer.valueOf(stack.getMetadata()));
        return (eggInfo != null) ? (renderPass == 0 ? eggInfo.primaryColor : eggInfo.secondaryColor) : 16777215;
    }
   
    /**  
    * Returns true if this item requires multiple render passes.
    */
    @SideOnly(Side.CLIENT)
    public boolean requiresMultipleRenderPasses() {
        return true;
    }

    /**
    * Returns an icon based on the item's damage and the render pass.
    */
    @SideOnly(Side.CLIENT)
    public IIcon getIconFromDamageForRenderPass(int damage, int renderPass) {
        return (renderPass > 0) ? theIcon : super.getIconFromDamageForRenderPass(damage, renderPass);
    }

    /**
    * Registers icons for this item.
    */
    @SideOnly(Side.CLIENT)
    public void registerIcons(IIconRegister iconRegister) {
        this.itemIcon = iconRegister.registerIcon(this.getIconString());
        this.theIcon = iconRegister.registerIcon(this.getIconString() + "_overlay");
    }
}
 
Последнее редактирование:
173
13
25
Для чего ты вызываешь super? Если ты ставишь основную иконку предмета как icons[0] = reg.registerIcon(Vars.MODID + ":" + names[0]);
Java:
@Override
@SideOnly(Side.CLIENT)
public void registerIcons(IIconRegister reg) {
    super.registerIcons(reg);
 
    icons = new IIcon[colors.length > 0 ? 2 : names.length];
    if (colors.length > 0) {
        icons[0] = reg.registerIcon(Vars.MODID + ":" + names[0]);
        icons[1] = reg.registerIcon(Vars.MODID + ":" + names[0] + "_overlay");
        return;
    }
 
    for (int i = 1; i < names.length; i++)
        icons[i-1] = reg.registerIcon(Vars.MODID + ":" + names[0] + "_" + names[i]);
    }
}

P.S. вместо icons[0] юзай itemIcon из Item, если ты хочешь ставить основную иконку предмета.
 
Последнее редактирование:
192
2
9
Для чего ты вызываешь super?
Crash:
java.lang.NullPointerException: Rendering item
    at net.minecraft.client.renderer.entity.RenderItem.func_94149_a(RenderItem.java:732)
    at net.minecraft.client.renderer.entity.RenderItem.renderItemIntoGUI(RenderItem.java:498)
    at net.minecraft.client.renderer.entity.RenderItem.func_82406_b(RenderItem.java:565)
    at net.minecraft.client.gui.GuiIngame.func_73832_a(GuiIngame.java:955)
    at net.minecraftforge.client.GuiIngameForge.renderHotbar(GuiIngameForge.java:206)
    at net.minecraftforge.client.GuiIngameForge.func_73830_a(GuiIngameForge.java:141)
    at net.minecraft.client.renderer.EntityRenderer.func_78480_b(EntityRenderer.java:1038)
    at net.minecraft.client.Minecraft.func_71411_J(Minecraft.java:1001)
    at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:898)
    at net.minecraft.client.main.Main.main(SourceFile:148)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
    at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
    at pro.gravit.launcher.laUncHeriQOlsd.lAuNCHER57hwBy(Unknown Source)
    at pro.gravit.launcher.laUncHeriQOlsd.main(Unknown Source)

getColorFromItemStack:
    @SideOnly(Side.CLIENT)
    public int getColorFromItemStack(ItemStack stack, int renderPass) {
        EntityList.EntityEggInfo entityegginfo = (EntityList.EntityEggInfo)EntityList.entityEggs.get(Integer.valueOf(stack.getMetadata()));
        return (eggInfo != null) ? (renderPass == 0 ? eggInfo.primaryColor : eggInfo.secondaryColor) : 16777215;
    }
Я видел этот метод, но не сообразил от каких условий зависит цвет в данном случае. А всё потому, что я так же не понимал, как работает renderPass переменная.

Итого получается:
Если мы хотим красить отдельные части текстуры, нам потребуется собрать её из нескольких слоёв, как это сделано в яйцах призыва или в кожанке. Но по-умолчанию предусмотрено 2 слоя. Чтобы активировать этот режим, нужно вернуть true в методе ниже:
Code:
@SideOnly(Side.CLIENT)
public boolean requiresMultipleRenderPasses() {
    return true;
}

Затем нужно определить, какую мы будем возвращать текстуру во время рендера конкретного слоя. Когда рендерится конкретный слой? Об этом подскажет та самая переменная renderPass, где 0 будет восприниматься, как самый первый слой и т.д.. Задавать текстуры нужно в методе ниже:
Code:
@SideOnly(Side.CLIENT)
public IIcon getIconFromDamageForRenderPass(int meta, int rPass) {
    return rPass > 0 ? super.getIconFromDamageForRenderPass(meta, rPass) : icons[1];
    // return rPass > 0 ? иконка слоя : базовая иконка;
}

Цвет конкретного слоя работает аналогично наложению текстуры этого слоя и указывается в другом методе и базовый цвет устанавливается как 16777215, если текстуру красить не нужно:
Code:
@Override
@SideOnly(Side.CLIENT)
public int getColorFromItemStack(ItemStack stack, int rPass) {
    return rPass > 0 && colors.length >= rPass ? colors[stack.getItemDamage()] : 16777215;
    // rPass > 0 ? цвет слоя : базовый цвет;
}

Поправьте, если где ошибся, исправлю)
 
Сверху