    001package net.minecraftforge.liquids;
    002
    003import static cpw.mods.fml.relauncher.Side.CLIENT;
    004
    005import com.google.common.base.Objects;
    006
    007import cpw.mods.fml.relauncher.SideOnly;
    008import net.minecraft.block.Block;
    009import net.minecraft.block.BlockFluid;
    010import net.minecraft.client.renderer.texture.TextureManager;
    011import net.minecraft.item.Item;
    012import net.minecraft.item.ItemStack;
    013import net.minecraft.nbt.NBTTagCompound;
    014import net.minecraft.util.Icon;
    015
    016/**
    017 * ItemStack substitute for liquids
    018 * Things of note: they are equal if their items are equal. Amount does NOT matter for java equals() testing
    019 * <br/>
    020 * The canonical liquidstack is probably the only one that has a lot of the rendering data on it. Use {@link #canonical()}
    021 * to get it.
    022 *
    023 * @author SirSengir
    024 */
    025public class LiquidStack
    026{
    027    public final int itemID;
    028    public int amount;
    029    public final int itemMeta;
    030    public NBTTagCompound extra;
    031
    032    public LiquidStack(int itemID,  int amount) { this(itemID,        amount, 0); }
    033    public LiquidStack(Item item,   int amount) { this(item.itemID,   amount, 0); }
    034    public LiquidStack(Block block, int amount) { this(block.blockID, amount, 0); }
    035
    036    public LiquidStack(int itemID, int amount, int itemDamage)
    037    {
    038        this.itemID = itemID;
    039        this.amount = amount;
    040        this.itemMeta = itemDamage;
    041    }
    042
    043    public LiquidStack(int itemID, int amount, int itemDamage, NBTTagCompound nbt)
    044    {
    045        this(itemID, amount, itemDamage);
    046        if (nbt != null)
    047        {
    048            extra = (NBTTagCompound)nbt.copy();
    049        }
    050    }
    051
    052    public NBTTagCompound writeToNBT(NBTTagCompound nbt)
    053    {
    054        nbt.setInteger("Amount", amount);
    055        nbt.setShort("Id", (short)itemID);
    056        nbt.setShort("Meta", (short)itemMeta);
    057        nbt.setString("LiquidName", LiquidDictionary.findLiquidName(this));
    058        if (extra != null)
    059        {
    060            nbt.setTag("extra", extra);
    061        }
    062        return nbt;
    063    }
    064
    065
    066    /**
    067     * NO-OP now. Use {@link #loadLiquidStackFromNBT(NBTTagCompound)} to get a new instance
    068     *
    069     * @param nbt
    070     */
    071    @Deprecated
    072    public void readFromNBT(NBTTagCompound nbt)
    073    {
    074    }
    075
    076    /**
    077     * @return A copy of this LiquidStack
    078     */
    079    public LiquidStack copy()
    080    {
    081        return new LiquidStack(itemID, amount, itemMeta, extra);
    082    }
    083
    084    /**
    085     * @param other
    086     * @return true if this LiquidStack contains the same liquid as the one passed in.
    087     */
    088    public boolean isLiquidEqual(LiquidStack other)
    089    {
    090        return other != null && itemID == other.itemID && itemMeta == other.itemMeta && (extra == null ? other.extra == null : extra.equals(other.extra));
    091    }
    092
    093    /**
    094     * @param other
    095     * @return true if this LiquidStack contains the other liquid (liquids are equal and amount >= other.amount).
    096     */
    097    public boolean containsLiquid(LiquidStack other)
    098    {
    099        return isLiquidEqual(other) && amount >= other.amount;
    100    }
    101
    102    /**
    103     * @param other ItemStack containing liquids.
    104     * @return true if this LiquidStack contains the same liquid as the one passed in.
    105     */
    106    public boolean isLiquidEqual(ItemStack other)
    107    {
    108        if (other == null)
    109        {
    110            return false;
    111        }
    112
    113        if (itemID == other.itemID && itemMeta == other.getItemDamage())
    114        {
    115            return true;
    116        }
    117
    118        return isLiquidEqual(LiquidContainerRegistry.getLiquidForFilledItem(other));
    119    }
    120
    121    /**
    122     * @return ItemStack representation of this LiquidStack
    123     */
    124    public ItemStack asItemStack()
    125    {
    126        ItemStack stack = new ItemStack(itemID, 1, itemMeta);
    127        if (extra != null)
    128        {
    129            stack.stackTagCompound = (NBTTagCompound)extra.copy();
    130        }
    131        return stack;
    132    }
    133
    134    /**
    135     * Reads a liquid stack from the passed nbttagcompound and returns it.
    136     *
    137     * @param nbt
    138     * @return the liquid stack
    139     */
    140    public static LiquidStack loadLiquidStackFromNBT(NBTTagCompound nbt)
    141    {
    142        if (nbt == null)
    143        {
    144            return null;
    145        }
    146        String liquidName = nbt.getString("LiquidName");
    147        int itemID = nbt.getShort("Id");
    148        int itemMeta = nbt.getShort("Meta");
    149        LiquidStack liquid = LiquidDictionary.getCanonicalLiquid(liquidName);
    150        if(liquid != null) {
    151            itemID = liquid.itemID;
    152            itemMeta = liquid.itemMeta;
    153        }
    154        // if the item is not existent, and no liquid dictionary is found, null returns
    155        else if (Item.itemsList[itemID] == null)
    156        {
    157            return null;
    158        }
    159        int amount = nbt.getInteger("Amount");
    160        LiquidStack liquidstack = new LiquidStack(itemID, amount, itemMeta);
    161        if (nbt.hasKey("extra"))
    162        {
    163            liquidstack.extra = nbt.getCompoundTag("extra");
    164        }
    165        return liquidstack.itemID == 0 ? null : liquidstack;
    166    }
    167
    168    private String textureSheet = "/terrain.png";
    169
    170    /**
    171     * Return the textureSheet used for this liquid stack's texture Icon
    172     * Defaults to '/terrain.png'
    173     *
    174     * See {@link #getRenderingIcon()} for the actual icon
    175     *
    176     * @return The texture sheet
    177     */
    178    public String getTextureSheet()
    179    {
    180        return textureSheet;
    181    }
    182
    183    /**
    184     * Set the texture sheet for this icon (usually /terrain.png or /gui/items.png)
    185     *
    186     * See also the {@link #setRenderingIcon(Icon)} for the icon itself
    187     *
    188     * @param textureSheet
    189     * @return the liquid stack
    190     */
    191    public LiquidStack setTextureSheet(String textureSheet)
    192    {
    193        this.textureSheet = textureSheet;
    194        return this;
    195    }
    196    @SideOnly(CLIENT)
    197    private Icon renderingIcon;
    198
    199    /**
    200     * Get the rendering icon for this liquid stack, for presentation in the world or in GUIs.
    201     * Defaults to handling water and lava, and returns the set rendering icon otherwise.
    202     *
    203     * See {@link #getTextureSheet()} to get the texture sheet this icon is associated with
    204     *
    205     * @return The icon for rendering this liquid
    206     */
    207    @SideOnly(CLIENT)
    208    public Icon getRenderingIcon()
    209    {
    210        if (itemID == Block.waterStill.blockID)
    211        {
    212            return BlockFluid.func_94424_b("water");
    213        }
    214        else if (itemID == Block.lavaStill.blockID)
    215        {
    216            return BlockFluid.func_94424_b("lava");
    217        }
    218        return renderingIcon;
    219    }
    220
    221    /**
    222     * Set the icon for rendering this liquid
    223     * It should be refreshed whenever textures are refreshed.
    224     *
    225     * See also {@link #setTextureSheet(String)} for setting the sheet this icon is associated with
    226     *
    227     * @param icon The icon to render
    228     * @return The liquid stack
    229     */
    230    @SideOnly(CLIENT)
    231    public LiquidStack setRenderingIcon(Icon icon)
    232    {
    233        this.renderingIcon = icon;
    234        return this;
    235    }
    236
    237    @Override
    238    public final int hashCode()
    239    {
    240        return 31 * itemMeta + itemID;
    241    }
    242
    243    @Override
    244    public final boolean equals(Object ob)
    245    {
    246        if (ob instanceof LiquidStack)
    247        {
    248            LiquidStack ls = (LiquidStack)ob;
    249            return ls.itemID == itemID && ls.itemMeta == itemMeta && (extra == null ? ls.extra == null : extra.equals(ls.extra));
    250        }
    251        return false;
    252    }
    253
    254
    255    /**
    256     * Get the canonical version of this liquid stack (will contain things like icons and texturesheets)
    257     * @return The canonical liquidstack
    258     */
    259    public LiquidStack canonical()
    260    {
    261        return LiquidDictionary.getCanonicalLiquid(this);
    262    }
    263}