package openblocks.common.item; import com.google.common.base.Objects; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.util.List; import net.minecraft.block.Block; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase.NBTPrimitive; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.IIcon; import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import openblocks.Config; import openblocks.common.tileentity.TileEntityImaginary; import openblocks.common.tileentity.TileEntityImaginary.ICollisionData; import openblocks.common.tileentity.TileEntityImaginary.PanelData; import openblocks.common.tileentity.TileEntityImaginary.StairsData; import openmods.item.ItemOpenBlock; import openmods.utils.BlockUtils; import openmods.utils.ColorUtils; import openmods.utils.ColorUtils.ColorMeta; import openmods.utils.ItemUtils; public class ItemImaginary extends ItemOpenBlock { public static final float CRAFTING_COST = 1.0f; public static final String TAG_COLOR = "Color"; public static final String TAG_USES = "Uses"; public static final String TAG_MODE = "Mode"; public static final int DAMAGE_PENCIL = 0; public static final int DAMAGE_CRAYON = 1; private enum PlacementMode { BLOCK(1.0f, "block", "overlay_block", false) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { return TileEntityImaginary.DUMMY; } }, PANEL(0.5f, "panel", "overlay_panel", false) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { return new PanelData(1.0f); } }, HALF_PANEL(0.5f, "half_panel", "overlay_half", false) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { return new PanelData(0.5f); } }, STAIRS(0.75f, "stairs", "overlay_stairs", false) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { ForgeDirection dir = BlockUtils.get2dOrientation(player); return new StairsData(0.5f, 1.0f, dir); } }, INV_BLOCK(1.5f, "inverted_block", "overlay_inverted_block", true) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { return TileEntityImaginary.DUMMY; } }, INV_PANEL(1.0f, "inverted_panel", "overlay_inverted_panel", true) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { return new PanelData(1.0f); } }, INV_HALF_PANEL(1.0f, "inverted_half_panel", "overlay_inverted_half", true) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { return new PanelData(0.5f); } }, INV_STAIRS(1.25f, "inverted_stairs", "overlay_inverted_stairs", true) { @Override public ICollisionData createCollisionData(ItemStack stack, EntityPlayer player) { ForgeDirection dir = BlockUtils.get2dOrientation(player); return new StairsData(0.5f, 1.0f, dir); } }; public final float cost; public final String name; public final String overlayName; public final boolean isInverted; public IIcon overlay; private PlacementMode(float cost, String name, String overlayName, boolean isInverted) { this.cost = cost; this.name = "openblocks.misc.mode." + name; this.overlayName = "openblocks:" + overlayName; this.isInverted = isInverted; } public abstract ICollisionData createCollisionData(ItemStack stack, EntityPlayer player); public static final PlacementMode[] VALUES = values(); } public static float getUses(NBTTagCompound tag) { NBTBase value = tag.getTag(TAG_USES); if (value == null) return 0; if (value instanceof NBTPrimitive) return ((NBTPrimitive)value).func_150288_h(); throw new IllegalStateException("Invalid tag type: " + value); } public static float getUses(ItemStack stack) { NBTTagCompound tag = ItemUtils.getItemTag(stack); return getUses(tag); } public static PlacementMode getMode(NBTTagCompound tag) { int value = tag.getByte(TAG_MODE); return PlacementMode.VALUES[value]; } public static PlacementMode getMode(ItemStack stack) { NBTTagCompound tag = ItemUtils.getItemTag(stack); return getMode(tag); } public static boolean isCrayon(ItemStack stack) { return stack.getItemDamage() == DAMAGE_CRAYON; } public ItemImaginary(Block block) { super(block); setMaxStackSize(1); setHasSubtypes(true); setMaxDamage(0); } public static ItemStack setupValues(Integer color, ItemStack result) { return setupValues(color, result, Config.imaginaryItemUseCount); } public static ItemStack setupValues(Integer color, ItemStack result, float uses) { NBTTagCompound tag = ItemUtils.getItemTag(result); if (color != null) { tag.setInteger(TAG_COLOR, color); result.setItemDamage(DAMAGE_CRAYON); } tag.setFloat(TAG_USES, uses); return result; } @Override protected void afterBlockPlaced(ItemStack stack, EntityPlayer player, World world, int x, int y, int z) { NBTTagCompound tag = ItemUtils.getItemTag(stack); NBTTagInt color = (NBTTagInt)tag.getTag(TAG_COLOR); PlacementMode mode = getMode(tag); ICollisionData collisions = mode.createCollisionData(stack, player); world.setTileEntity(x, y, z, new TileEntityImaginary(color == null? null : color.func_150287_d(), mode.isInverted, collisions)); if (!player.capabilities.isCreativeMode) { float uses = Math.max(getUses(tag) - mode.cost, 0); tag.setFloat(TAG_USES, uses); if (uses <= 0) stack.stackSize = 0; } } @Override public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) { if (stack == null) return false; NBTTagCompound tag = ItemUtils.getItemTag(stack); float uses = getUses(tag); if (uses <= 0) { stack.stackSize = 0; return true; } if (uses < getMode(tag).cost) return false; return super.onItemUse(stack, player, world, x, y, z, side, hitX, hitY, hitZ); } @Override public String getUnlocalizedName(ItemStack stack) { NBTTagCompound tag = ItemUtils.getItemTag(stack); return tag.hasKey(TAG_COLOR)? "item.openblocks.crayon" : "item.openblocks.pencil"; } @Override public String getUnlocalizedName() { return "item.openblocks.imaginary"; } @Override @SideOnly(Side.CLIENT) @SuppressWarnings({ "unchecked", "rawtypes" }) public void addInformation(ItemStack stack, EntityPlayer player, List result, boolean extended) { NBTTagCompound tag = ItemUtils.getItemTag(stack); result.add(StatCollector.translateToLocalFormatted("openblocks.misc.uses", getUses(tag))); NBTTagInt color = (NBTTagInt)tag.getTag(TAG_COLOR); if (color != null) result.add(StatCollector.translateToLocalFormatted("openblocks.misc.color", color.func_150287_d())); PlacementMode mode = getMode(tag); String translatedMode = StatCollector.translateToLocal(mode.name); result.add(StatCollector.translateToLocalFormatted("openblocks.misc.mode", translatedMode)); } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public void getSubItems(Item item, CreativeTabs tab, List result) { result.add(setupValues(null, new ItemStack(this, 1, DAMAGE_PENCIL))); for (ColorMeta color : ColorUtils.getAllColors()) result.add(setupValues(color.rgb, new ItemStack(this, 1, DAMAGE_CRAYON))); } @Override public int getSpriteNumber() { return 1; // render as item } private IIcon iconCrayonBackground; private IIcon iconCrayonColor; private IIcon iconPencil; private IIcon iconBlank; @Override @SideOnly(Side.CLIENT) public void registerIcons(IIconRegister registry) { iconCrayonBackground = registry.registerIcon("openblocks:crayon_1"); iconCrayonColor = registry.registerIcon("openblocks:crayon_2"); iconPencil = registry.registerIcon("openblocks:pencil"); iconBlank = registry.registerIcon("openblocks:blank"); for (PlacementMode mode : PlacementMode.VALUES) mode.overlay = registry.registerIcon(mode.overlayName); } private IIcon getOverlayIcon(ItemStack stack, boolean inGui) { return inGui? getMode(stack).overlay : iconBlank; } private IIcon getIcon(ItemStack stack, int pass, boolean inGui) { if (!isCrayon(stack)) return pass == 1? getOverlayIcon(stack, inGui) : iconPencil; switch (pass) { case 0: return iconCrayonBackground; case 1: return iconCrayonColor; case 2: return getOverlayIcon(stack, inGui); } throw new IllegalArgumentException("Invalid pass: " + pass); } @Override @SideOnly(Side.CLIENT) public final IIcon getIcon(ItemStack stack, int pass) { return getIcon(stack, pass, true); } @Override @SideOnly(Side.CLIENT) public IIcon getIcon(ItemStack stack, int pass, EntityPlayer player, ItemStack usingItem, int useRemaining) { return getIcon(stack, pass, false); } @Override @SideOnly(Side.CLIENT) public int getColorFromItemStack(ItemStack stack, int pass) { if (isCrayon(stack) && pass == 1) return Objects.firstNonNull(ItemUtils.getInt(stack, TAG_COLOR), 0x000000); return 0xFFFFFF; } @Override @SideOnly(Side.CLIENT) public boolean requiresMultipleRenderPasses() { return true; } @Override public int getRenderPasses(int metadata) { return metadata == DAMAGE_CRAYON? 3 : 2; } @Override public boolean doesContainerItemLeaveCraftingGrid(ItemStack stack) { return false; } @Override public boolean hasContainerItem(ItemStack stack) { return true; } @Override public ItemStack getContainerItem(ItemStack stack) { NBTTagCompound tag = ItemUtils.getItemTag(stack); float uses = getUses(tag) - CRAFTING_COST; if (uses <= 0) return null; ItemStack copy = stack.copy(); NBTTagCompound copyTag = ItemUtils.getItemTag(copy); copyTag.setFloat(TAG_USES, uses); return copy; } @Override public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) { NBTTagCompound tag = ItemUtils.getItemTag(stack); if (getUses(tag) <= 0) { stack.stackSize = 0; } else if (player.isSneaking()) { byte modeId = tag.getByte(TAG_MODE); modeId = (byte)((modeId + 1) % PlacementMode.VALUES.length); tag.setByte(TAG_MODE, modeId); if (world.isRemote) { PlacementMode mode = PlacementMode.VALUES[modeId]; ChatComponentTranslation modeName = new ChatComponentTranslation(mode.name); player.addChatComponentMessage(new ChatComponentTranslation("openblocks.misc.mode", modeName)); } } return stack; } }