package gtPlusPlus.xmod.gregtech.api.items;
import static gregtech.api.enums.GTValues.D1;
import static gregtech.api.enums.Mods.GTPlusPlus;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import gregtech.api.GregTechAPI;
import gregtech.api.enums.Materials;
import gregtech.api.enums.SubTag;
import gregtech.api.enums.TCAspects.TC_AspectStack;
import gregtech.api.interfaces.IFoodStat;
import gregtech.api.interfaces.IIconContainer;
import gregtech.api.interfaces.IItemContainer;
import gregtech.api.objects.ItemData;
import gregtech.api.util.GTLanguageManager;
import gregtech.api.util.GTOreDictUnificator;
import gregtech.api.util.GTUtility;
import gtPlusPlus.core.creative.AddToCreativeTab;
import gtPlusPlus.xmod.gregtech.api.interfaces.internal.IItemBehaviour;
public abstract class GTMetaItem extends GTMetaItemBase {
/**
* All instances of this Item Class are listed here. This gets used to register the Renderer to all Items of this
* Type, if useStandardMetaItemRenderer() returns true.
*
* You can also use the unlocalized Name gotten from getUnlocalizedName() as Key if you want to get a specific Item.
*/
public static final HashMap sInstances = new HashMap<>();
/* ---------- CONSTRUCTOR AND MEMBER VARIABLES ---------- */
public final short mOffset, mItemAmount;
public final BitSet mEnabledItems;
public final BitSet mVisibleItems;
public final IIcon[][] mIconList;
public final HashMap mFoodStats = new HashMap<>();
public final HashMap mElectricStats = new HashMap<>();
public final HashMap mFluidContainerStats = new HashMap<>();
public final HashMap mBurnValues = new HashMap<>();
/**
* Creates the Item using these Parameters.
*
* @param aUnlocalized The Unlocalized Name of this Item.
*/
public GTMetaItem(final String aUnlocalized, final short aOffset, final short aItemAmount) {
super(aUnlocalized);
this.setCreativeTab(AddToCreativeTab.tabMachines);
this.setHasSubtypes(true);
this.setMaxDamage(0);
this.mEnabledItems = new BitSet(aItemAmount);
this.mVisibleItems = new BitSet(aItemAmount);
this.mOffset = (short) Math.min(32766, aOffset);
this.mItemAmount = (short) Math.min(aItemAmount, 32766 - this.mOffset);
this.mIconList = new IIcon[aItemAmount][1];
sInstances.put(this.getUnlocalizedName(), this);
}
/**
* This adds a Custom Item to the ending Range.
*
* @param aID The Id of the assigned Item [0 - mItemAmount] (The MetaData gets auto-shifted by +mOffset)
* @param aEnglish The Default Localized Name of the created Item
* @param aToolTip The Default ToolTip of the created Item, you can also insert null for having no ToolTip
* @param aFoodBehavior The Food Value of this Item. Can be null aswell. Just a convenience thing.
* @param aRandomData The OreDict Names you want to give the Item. Also used for TC Aspects and some other things.
* @return An ItemStack containing the newly created Item.
*/
public final ItemStack addItem(final int aID, final String aEnglish, String aToolTip, final Object... aRandomData) {
if (aToolTip == null) {
aToolTip = "";
}
if ((aID >= 0) && (aID < this.mItemAmount)) {
final ItemStack rStack = new ItemStack(this, 1, this.mOffset + aID);
this.mEnabledItems.set(aID);
this.mVisibleItems.set(aID);
GTLanguageManager.addStringLocalization(this.getUnlocalizedName(rStack) + ".name", aEnglish);
GTLanguageManager.addStringLocalization(this.getUnlocalizedName(rStack) + ".tooltip", aToolTip);
final List tAspects = new ArrayList<>();
// Important Stuff to do first
for (final Object tRandomData : aRandomData) {
if (tRandomData instanceof SubTag) {
if (tRandomData == SubTag.INVISIBLE) {
this.mVisibleItems.set(aID, false);
continue;
}
if (tRandomData == SubTag.NO_UNIFICATION) {
GTOreDictUnificator.addToBlacklist(rStack);
continue;
}
}
}
// now check for the rest
for (final Object tRandomData : aRandomData) {
if (tRandomData != null) {
boolean tUseOreDict = true;
if (tRandomData instanceof IItemBehaviour) {
this.addItemBehavior(this.mOffset + aID, (IItemBehaviour) tRandomData);
tUseOreDict = false;
}
if (tRandomData instanceof IItemContainer) {
((IItemContainer) tRandomData).set(rStack);
tUseOreDict = false;
}
if (tRandomData instanceof SubTag) {
continue;
}
if (tRandomData instanceof TC_AspectStack) {
((TC_AspectStack) tRandomData).addToAspectList(tAspects);
continue;
}
if (tRandomData instanceof ItemData) {
if (GTUtility.isStringValid(tRandomData)) {
GTOreDictUnificator.registerOre(tRandomData, rStack);
} else {
GTOreDictUnificator.addItemData(rStack, (ItemData) tRandomData);
}
continue;
}
if (tUseOreDict) {
GTOreDictUnificator.registerOre(tRandomData, rStack);
continue;
}
}
}
if (GregTechAPI.sThaumcraftCompat != null) {
GregTechAPI.sThaumcraftCompat.registerThaumcraftAspectsToItem(rStack, tAspects, false);
}
return rStack;
}
return null;
}
/**
* Sets the Furnace Burn Value for the Item.
*
* @param aMetaValue the Meta Value of the Item you want to set it to. [0 - 32765]
* @param aValue 200 = 1 Burn Process = 500 EU, max = 32767 (that is 81917.5 EU)
* @return the Item itself for convenience in constructing.
*/
public final GTMetaItem setBurnValue(final int aMetaValue, final int aValue) {
if ((aMetaValue < 0) || (aMetaValue >= (this.mOffset + this.mEnabledItems.length())) || (aValue < 0)) {
return this;
}
if (aValue == 0) {
this.mBurnValues.remove((short) aMetaValue);
} else {
this.mBurnValues.put((short) aMetaValue, aValue > Short.MAX_VALUE ? Short.MAX_VALUE : (short) aValue);
}
return this;
}
/**
* @param aMetaValue the Meta Value of the Item you want to set it to. [0 - 32765]
* @param aMaxCharge Maximum Charge. (if this is == 0 it will remove the Electric Behavior)
* @param aTransferLimit Transfer Limit.
* @param aTier The electric Tier.
* @param aSpecialData If this Item has a Fixed Charge, like a SingleUse Battery (if > 0). Use -1 if you want to
* make this Battery chargeable (the use and canUse Functions will still discharge if you just
* use this) Use -2 if you want to make this Battery dischargeable. Use -3 if you want to make
* this Battery charge/discharge-able.
* @return the Item itself for convenience in constructing.
*/
public final GTMetaItem setElectricStats(final int aMetaValue, final long aMaxCharge, final long aTransferLimit,
final long aTier, final long aSpecialData, final boolean aUseAnimations) {
if ((aMetaValue < 0) || (aMetaValue >= (this.mOffset + this.mEnabledItems.length()))) {
return this;
}
if (aMaxCharge == 0) {
this.mElectricStats.remove((short) aMetaValue);
} else {
this.mElectricStats.put(
(short) aMetaValue,
new Long[] { aMaxCharge, Math.max(0, aTransferLimit), Math.max(-1, aTier), aSpecialData });
if ((aMetaValue >= this.mOffset) && aUseAnimations) {
this.mIconList[aMetaValue - this.mOffset] = Arrays.copyOf(
this.mIconList[aMetaValue - this.mOffset],
Math.max(9, this.mIconList[aMetaValue - this.mOffset].length));
}
}
return this;
}
/**
* @param aMetaValue the Meta Value of the Item you want to set it to. [0 - 32765]
* @param aMaxCharge Maximum Charge. (if this is == 0 it will remove the Electric Behavior)
* @param aTransferLimit Transfer Limit.
* @param aTier The electric Tier.
* @param aSpecialData If this Item has a Fixed Charge, like a SingleUse Battery (if > 0). Use -1 if you want to
* make this Battery chargeable (the use and canUse Functions will still discharge if you just
* use this) Use -2 if you want to make this Battery dischargeable. Use -3 if you want to make
* this Battery charge/discharge-able.
* @return the Item itself for convenience in constructing.
*/
public final GTMetaItem setFluidContainerStats(final int aMetaValue, final long aCapacity, final long aStacksize) {
if ((aMetaValue < 0) || (aMetaValue >= (this.mOffset + this.mEnabledItems.length()))) {
return this;
}
if (aCapacity < 0) {
this.mElectricStats.remove((short) aMetaValue);
} else {
this.mFluidContainerStats.put((short) aMetaValue, new Long[] { aCapacity, Math.max(1, aStacksize) });
}
return this;
}
/**
* @return if this MetaGenerated Item should use my Default Renderer System.
*/
public boolean useStandardMetaItemRenderer() {
return true;
}
/**
* @return the Color Modulation the Material is going to be rendered with.
*/
public short[] getRGBa(final ItemStack aStack) {
return Materials._NULL.getRGBA();
}
/**
* @return the Icon the Material is going to be rendered with.
*/
public IIconContainer getIconContainer(final int aMetaData) {
return null;
}
/* ---------- INTERNAL OVERRIDES ---------- */
@Override
public ItemStack onItemRightClick(final ItemStack aStack, final World aWorld, final EntityPlayer aPlayer) {
return super.onItemRightClick(aStack, aWorld, aPlayer);
}
@Override
public int getMaxItemUseDuration(final ItemStack aStack) {
return this.mFoodStats.get((short) this.getDamage(aStack)) == null ? 0 : 32;
}
@Override
public EnumAction getItemUseAction(final ItemStack aStack) {
return EnumAction.none;
}
@Override
public final ItemStack onEaten(final ItemStack aStack, final World aWorld, final EntityPlayer aPlayer) {
final IFoodStat tStat = this.mFoodStats.get((short) this.getDamage(aStack));
if (tStat != null) {}
return aStack;
}
@Override
@SideOnly(Side.CLIENT)
public void getSubItems(final Item var1, final CreativeTabs aCreativeTab, final List aList) {
for (int i = 0, j = this.mEnabledItems.length(); i < j; i++) {
if (this.mVisibleItems.get(i) || (D1 && this.mEnabledItems.get(i))) {
final Long[] tStats = this.mElectricStats.get((short) (this.mOffset + i));
if ((tStats != null) && (tStats[3] < 0)) {
final ItemStack tStack = new ItemStack(this, 1, this.mOffset + i);
this.setCharge(tStack, Math.abs(tStats[0]));
this.isItemStackUsable(tStack);
aList.add(tStack);
}
if ((tStats == null) || (tStats[3] != -2)) {
final ItemStack tStack = new ItemStack(this, 1, this.mOffset + i);
this.isItemStackUsable(tStack);
aList.add(tStack);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public final void registerIcons(final IIconRegister aIconRegister) {
for (short i = 0, j = (short) this.mEnabledItems.length(); i < j; i++) {
if (this.mEnabledItems.get(i)) {
for (byte k = 1; k < this.mIconList[i].length; k++) {
this.mIconList[i][k] = aIconRegister
.registerIcon(GTPlusPlus.ID + ":" + this.getUnlocalizedName() + "/" + i + "/" + k);
}
this.mIconList[i][0] = aIconRegister
.registerIcon(GTPlusPlus.ID + ":" + this.getUnlocalizedName() + "/" + i);
}
}
}
@Override
public final Long[] getElectricStats(final ItemStack aStack) {
return this.mElectricStats.get((short) aStack.getItemDamage());
}
@Override
public final Long[] getFluidContainerStats(final ItemStack aStack) {
return this.mFluidContainerStats.get((short) aStack.getItemDamage());
}
@Override
public int getItemEnchantability() {
return 0;
}
@Override
public boolean isBookEnchantable(final ItemStack aStack, final ItemStack aBook) {
return false;
}
@Override
public boolean getIsRepairable(final ItemStack aStack, final ItemStack aMaterial) {
return false;
}
@Override
public int getColorFromItemStack(final ItemStack stack, int HEX_OxFFFFFF) {
if (stack.getDisplayName()
.contains("LuV")) {
HEX_OxFFFFFF = 0xffffcc;
} else if (stack.getDisplayName()
.contains("ZPM")) {
HEX_OxFFFFFF = 0xace600;
} else if (stack.getDisplayName()
.contains("UV")) {
HEX_OxFFFFFF = 0xffff00;
} else if (stack.getDisplayName()
.contains("MAX")) {
HEX_OxFFFFFF = 0xff0000;
} else {
HEX_OxFFFFFF = 0xffffff;
}
return HEX_OxFFFFFF;
}
}