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
031    public LiquidStack(int itemID,  int amount) { this(itemID,        amount, 0); }
032    public LiquidStack(Item item,   int amount) { this(item.itemID,   amount, 0); }
033    public LiquidStack(Block block, int amount) { this(block.blockID, amount, 0); }
034
035    public LiquidStack(int itemID, int amount, int itemDamage)
036    {
037        this.itemID = itemID;
038        this.amount = amount;
039        this.itemMeta = itemDamage;
040    }
041
042    public NBTTagCompound writeToNBT(NBTTagCompound nbt)
043    {
044        nbt.setInteger("Amount", amount);
045        nbt.setShort("Id", (short)itemID);
046        nbt.setShort("Meta", (short)itemMeta);
047        nbt.setString("LiquidName", LiquidDictionary.findLiquidName(this));
048        return nbt;
049    }
050
051
052    /**
053     * NO-OP now. Use {@link #loadLiquidStackFromNBT(NBTTagCompound)} to get a new instance
054     *
055     * @param nbt
056     */
057    @Deprecated
058    public void readFromNBT(NBTTagCompound nbt)
059    {
060    }
061
062    /**
063     * @return A copy of this LiquidStack
064     */
065    public LiquidStack copy()
066    {
067        return new LiquidStack(itemID, amount, itemMeta);
068    }
069
070    /**
071     * @param other
072     * @return true if this LiquidStack contains the same liquid as the one passed in.
073     */
074    public boolean isLiquidEqual(LiquidStack other)
075    {
076        return other != null && itemID == other.itemID && itemMeta == other.itemMeta;
077    }
078
079    /**
080     * @param other
081     * @return true if this LiquidStack contains the other liquid (liquids are equal and amount >= other.amount).
082     */
083    public boolean containsLiquid(LiquidStack other)
084    {
085        return isLiquidEqual(other) && amount >= other.amount;
086    }
087
088    /**
089     * @param other ItemStack containing liquids.
090     * @return true if this LiquidStack contains the same liquid as the one passed in.
091     */
092    public boolean isLiquidEqual(ItemStack other)
093    {
094        if (other == null)
095        {
096            return false;
097        }
098
099        if (itemID == other.itemID && itemMeta == other.getItemDamage())
100        {
101            return true;
102        }
103
104        return isLiquidEqual(LiquidContainerRegistry.getLiquidForFilledItem(other));
105    }
106
107    /**
108     * @return ItemStack representation of this LiquidStack
109     */
110    public ItemStack asItemStack()
111    {
112        return new ItemStack(itemID, 1, itemMeta);
113    }
114
115    /**
116     * Reads a liquid stack from the passed nbttagcompound and returns it.
117     *
118     * @param nbt
119     * @return the liquid stack
120     */
121    public static LiquidStack loadLiquidStackFromNBT(NBTTagCompound nbt)
122    {
123        if (nbt == null)
124        {
125            return null;
126        }
127        String liquidName = nbt.getString("LiquidName");
128        int itemID = nbt.getShort("Id");
129        int itemMeta = nbt.getShort("Meta");
130        LiquidStack liquid = LiquidDictionary.getCanonicalLiquid(liquidName);
131        if(liquid != null) {
132            itemID = liquid.itemID;
133            itemMeta = liquid.itemMeta;
134        }
135        // if the item is not existent, and no liquid dictionary is found, null returns
136        else if (Item.itemsList[itemID] == null)
137        {
138            return null;
139        }
140        int amount = nbt.getInteger("Amount");
141        LiquidStack liquidstack = new LiquidStack(itemID, amount, itemMeta);
142        return liquidstack.itemID == 0 ? null : liquidstack;
143    }
144
145    @SideOnly(CLIENT)
146    private String textureSheet = "/terrain.png";
147
148    /**
149     * Return the textureSheet used for this liquid stack's texture Icon
150     * Defaults to '/terrain.png'
151     *
152     * See {@link #getRenderingIcon()} for the actual icon
153     *
154     * @return The texture sheet
155     */
156    public String getTextureSheet()
157    {
158        return textureSheet;
159    }
160
161    /**
162     * Set the texture sheet for this icon (usually /terrain.png or /gui/items.png)
163     *
164     * See also the {@link #setRenderingIcon(Icon)} for the icon itself
165     *
166     * @param textureSheet
167     * @return the liquid stack
168     */
169    public LiquidStack setTextureSheet(String textureSheet)
170    {
171        this.textureSheet = textureSheet;
172        return this;
173    }
174    @SideOnly(CLIENT)
175    private Icon renderingIcon;
176
177    /**
178     * Get the rendering icon for this liquid stack, for presentation in the world or in GUIs.
179     * Defaults to handling water and lava, and returns the set rendering icon otherwise.
180     *
181     * See {@link #getTextureSheet()} to get the texture sheet this icon is associated with
182     *
183     * @return The icon for rendering this liquid
184     */
185    @SideOnly(CLIENT)
186    public Icon getRenderingIcon()
187    {
188        if (itemID == Block.waterStill.blockID)
189        {
190            return BlockFluid.func_94424_b("water");
191        }
192        else if (itemID == Block.lavaStill.blockID)
193        {
194            return BlockFluid.func_94424_b("lava");
195        }
196        return renderingIcon;
197    }
198
199    /**
200     * Set the icon for rendering this liquid
201     * It should be refreshed whenever textures are refreshed.
202     *
203     * See also {@link #setTextureSheet(String)} for setting the sheet this icon is associated with
204     *
205     * @param icon The icon to render
206     * @return The liquid stack
207     */
208    @SideOnly(CLIENT)
209    public LiquidStack setRenderingIcon(Icon icon)
210    {
211        this.renderingIcon = icon;
212        return this;
213    }
214
215    @Override
216    public final int hashCode()
217    {
218        return 31 * itemMeta + itemID;
219    }
220
221    @Override
222    public final boolean equals(Object ob)
223    {
224        if (ob instanceof LiquidStack)
225        {
226            LiquidStack ls = (LiquidStack)ob;
227            return ls.itemID == itemID && ls.itemMeta == itemMeta;
228        }
229        return false;
230    }
231
232
233    /**
234     * Get the canonical version of this liquid stack (will contain things like icons and texturesheets)
235     * @return The canonical liquidstack
236     */
237    public LiquidStack canonical()
238    {
239        return LiquidDictionary.getCanonicalLiquid(this);
240    }
241}