public class DeathlyWarpPageItem extends Item implements IColorable {
	public DeathlyWarpPageItem(String name) {
		setUnlocalizedName(name);
		setRegistryName(name);
		setMaxStackSize(16);
		setCreativeTab(WarpBookMod.tabBook);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public int getColor(ItemStack stack, int tintIndex) {
		switch(tintIndex) {
			case 0: return pageColor();
			case 1: return symbolColor();
			default: return 0x00FFFFFF;
		}
	}
	
	@SideOnly(Side.CLIENT)
	public int pageColor() {
		return WarpColors.DEATHLY.getColor();
	}
	
	@SideOnly(Side.CLIENT)
	public int symbolColor() {
		return 0x00BBBBBB;
	}
} public class LegacyWarpPageItem extends WarpPageItem {
	//private static final String[] itemMetaNames = new String[] { "unbound", "bound", "hyperbound", "deathly", "potato", "player" };

	public LegacyWarpPageItem(String name) {
		super(name);
		setHasSubtypes(true);
		setCreativeTab(null);
		setMaxDamage(0);
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
		ItemStack itemStack = player.getHeldItem(hand);
		
		ItemStack newStack;
		switch (itemStack.getItemDamage()) {
			default:
			case 0:
				newStack = new ItemStack(WarpBookMod.items.unboundWarpPageItem, itemStack.getCount());
				break;
			case 1:
				newStack = new ItemStack(WarpBookMod.items.locusWarpPageItem, itemStack.getCount());
				break;
			case 2:
				newStack = new ItemStack(WarpBookMod.items.hyperWarpPageItem, itemStack.getCount());
				break;
			case 3:
				newStack = new ItemStack(WarpBookMod.items.deathlyWarpPageItem, itemStack.getCount());
				break;
			case 5:
				newStack = new ItemStack(WarpBookMod.items.playerWarpPageItem, itemStack.getCount());
				break;
		}
		if (itemStack.hasTagCompound()) {
			newStack.setTagCompound(itemStack.getTagCompound());
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, newStack);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		tooltip.add(I18n.format("help.legacy"));
	}
	
	@SideOnly(Side.CLIENT)
	public int pageColor() {
		return 0x00BBBBBB;
	}
	
	@SideOnly(Side.CLIENT)
	public int symbolColor() {
		return 0x00666666;
	}
	
} public class UnboundWarpPageItem extends WarpPageItem {

	public UnboundWarpPageItem(String name) {
		super(name);
		setCreativeTab(WarpBookMod.tabBook);
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
		ItemStack stack = player.getHeldItem(hand);
		
		if (player.isSneaking()) {
			stack = WarpUtils.bindItemStackToPlayer(new ItemStack(WarpBookMod.items.playerWarpPageItem, stack.getCount()), player);
		}
		else {
			WarpUtils.bindItemStackToLocation(new ItemStack(WarpBookMod.items.locusWarpPageItem), world, player);
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, stack);
	}

	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flagIn) {
	}
	
} public class UnboundWarpPotionItem extends WarpPotionItem {
	
	public UnboundWarpPotionItem(String name) {
		super(name);
		setCreativeTab(WarpBookMod.tabBook);
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
		ItemStack stack = player.getHeldItem(hand);

		if (player.isSneaking()) {
			stack = WarpUtils.bindItemStackToPlayer(new ItemStack(WarpBookMod.items.playerWarpPotionItem, stack.getCount()), player);
		}
		else {
			WarpUtils.bindItemStackToLocation(new ItemStack(WarpBookMod.items.locusWarpPotionItem), world, player);
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, stack);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flagIn) {
	}
	
} public class WarpBookItem extends Item implements IColorable {
	
	public WarpBookItem(String name) {
		setUnlocalizedName(name);
		setRegistryName(name);
		setMaxStackSize(1);
		setCreativeTab(WarpBookMod.tabBook);
		setMaxDamage(0);
	}
	
	@Override
	public int getMaxItemUseDuration(ItemStack itemStack) {
		return 1;
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
		ItemStack itemStack = player.getHeldItem(hand);
		
		WarpBookMod.lastHeldBooks.put(player, itemStack);
		if (player.isSneaking()) {
			player.openGui(WarpBookMod.instance, WarpBookMod.WarpBookInventoryGuiIndex, world, (int)player.posX, (int)player.posY, (int)player.posZ);
		}
		else {
			player.openGui(WarpBookMod.instance, WarpBookMod.WarpBookWarpGuiIndex, world, (int)player.posX, (int)player.posY, (int)player.posZ);
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, itemStack);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flag) {
		try {
			tooltip.add(I18n.format("warpbook.booktooltip", stack.getTagCompound().getTagList("WarpPages", new NBTTagCompound().getId()).tagCount()));
		}
		catch (Exception e) {
			// no pages
		}
	}
	
	public boolean getIsRepairable(ItemStack p_82789_1_, ItemStack p_82789_2_) {
		return false;
	}
	
	public static int getRespawnsLeft(ItemStack item) {
		if (item.getTagCompound() == null) {
			item.setTagCompound(new NBTTagCompound());
		}
		return item.getTagCompound().getShort("deathPages");
	}
	
	public static void setRespawnsLeft(ItemStack item, int deaths) {
		if (item.getTagCompound() == null) {
			item.setTagCompound(new NBTTagCompound());
		}
		item.getTagCompound().setShort("deathPages", (short)deaths);
	}
	
	public static void decrRespawnsLeft(ItemStack item) {
		setRespawnsLeft(item, getRespawnsLeft(item) - 1);
	}
	
	public static int getCopyCost(ItemStack itemStack) {
		
		if(itemStack.getTagCompound() == null) {
			itemStack.setTagCompound(new NBTTagCompound()); 
		}
		
		NBTTagList items = itemStack.getTagCompound().getTagList("WarpPages", new NBTTagCompound().getId());
		int count = 0;
		for (int i = 0; i < items.tagCount(); ++i) {
			ItemStack item = new ItemStack(items.getCompoundTagAt(i));
			if (((WarpItem)item.getItem()).isWarpCloneable(item)) {
				count += item.getCount();
			}
		}
		return count;
	}
	
	public static ItemStack copyBook(World world, ItemStack book) {
		
		ItemStack stack = new ItemStack(WarpBookMod.items.warpBookItem, 1);
		NBTTagList pages = book.getTagCompound().getTagList("WarpPages", Constants.NBT.TAG_COMPOUND);
		NBTTagList destPages = new NBTTagList();
		for (int i = 0; i < pages.tagCount(); ++i) {
			NBTTagCompound page = pages.getCompoundTagAt(i);
			int slot = page.getInteger("Slot");
			ItemStack item = new ItemStack(page);
			if (item.getItem() instanceof IDeclareWarp && ((WarpItem)item.getItem()).isWarpCloneable(item)) {
				NBTTagCompound tag = new NBTTagCompound();
				item.writeToNBT(tag);
				tag.setInteger("Slot", slot);
				destPages.appendTag(tag);
			}
		}
		stack.setTagCompound(new NBTTagCompound());
		stack.getTagCompound().setTag("WarpPages", destPages);
		
		return stack;
	}

	@Override
	@SideOnly(Side.CLIENT)
	public int getColor(ItemStack stack, int tintIndex) {
		
		switch(tintIndex) {
			case 0: {
				if(stack.hasTagCompound() && stack.getTagCompound().hasKey("color")) {
					return stack.getTagCompound().getInteger("color");
				}
				return WarpColors.LEATHER.getColor();//Leather
			}
			case 1: return WarpColors.UNBOUND.getColor();//The pages
			default: return 0xFFFFFFFF;//The ender pearl
		}
	}
	
} public class WarpItem extends Item implements IDeclareWarp, IColorable {
	
	public static final String unbound = "§4§kUnbound";
	public static final String ttprefix = "§a";
	
	public Warp warp = new Warp();
	public boolean cloneable = false;;
	
	public WarpItem(String name) {
		setUnlocalizedName(name);
		setRegistryName(name);
	}
	
	public WarpItem setWarp(Warp warp) {
		this.warp = warp;
		return this;
	}

	public WarpItem setCloneable(boolean is) {
		this.cloneable = is;
		return this;
	}
	
	@Override
	public String getName(World world, ItemStack stack) {
		return warp.getName(world, stack);
	}
	
	@Override
	public Waypoint getWaypoint(EntityPlayer player, ItemStack stack) {
		return warp.getWaypoint(player, stack);
	}
	
	@Override
	public boolean hasValidData(ItemStack stack) {
		return warp.hasValidData(stack);
	}

	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flagIn) {
		warp.addInformation(stack, world, tooltip, flagIn);
	}
	
	/** Can this be copied to a page? Either in the book cloner or via a copy recipe */
	public boolean isWarpCloneable(ItemStack stack) {
		return cloneable;
	}

	public boolean canGoInBook() {
		return false;
	}

	@Override
	@SideOnly(Side.CLIENT)
	public int getColor(ItemStack stack, int tintIndex) {
		return 0xFFFFFFFF;
	}
	
	@SideOnly(Side.CLIENT)
	public WarpColors getWarpColor() {
		return warp.getColor();
	}
	
} public class WarpPageItem extends WarpItem {
	
	public WarpPageItem(String name) {
		super(name);
		setMaxStackSize(64);
	}
	
	@Override
	public int getMaxItemUseDuration(ItemStack stack) {
		return 1;
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
		ItemStack itemStack = player.getHeldItem(hand);
		
		WarpBookMod.warpDrive.handleWarp(player, itemStack);

		return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, itemStack);
	}
	
	@Override
	public boolean canGoInBook() {
		return true;
	}

	@Override
	@SideOnly(Side.CLIENT)
	public int getColor(ItemStack stack, int tintIndex) {
		switch(tintIndex) {
			case 0: return pageColor();
			case 1: return symbolColor();
			default: return 0x00FFFFFF;
		}
	}
	
	@SideOnly(Side.CLIENT)
	public int pageColor() {
		return WarpColors.UNBOUND.getColor();
	}
	
	@SideOnly(Side.CLIENT)
	public int symbolColor() {
		return getWarpColor().getColor();
	}

} public class WarpPotionItem extends WarpItem {

	public WarpPotionItem(String name) {
		super(name);
		setMaxStackSize(1);
		setContainerItem(Items.GLASS_BOTTLE);
	}
	
	@Override
	public EnumAction getItemUseAction(ItemStack stack) {
		return hasValidData(stack) ? EnumAction.DRINK : EnumAction.NONE;
    }
	
	@Override
	public ItemStack onItemUseFinish(ItemStack stack, World world, EntityLivingBase player) {
		
		if(player instanceof EntityPlayer) {
			WarpBookMod.warpDrive.handleWarp((EntityPlayer) player, stack);
	        return new ItemStack(Items.GLASS_BOTTLE);
		}
		
        return ItemStack.EMPTY;
	}
	
	@Override
	public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
        player.setActiveHand(hand);
		ItemStack stack = player.getHeldItem(hand);
		
		if (player instanceof EntityPlayerMP) {
            EntityPlayerMP entityplayermp = (EntityPlayerMP)player;
            CriteriaTriggers.CONSUME_ITEM.trigger(entityplayermp, stack);
            entityplayermp.addStat(StatList.getObjectUseStats(this));
		}
		
		if(!hasValidData(stack)) {
			stack = new ItemStack(Items.GLASS_BOTTLE, stack.getCount());
		}
		
		return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, stack);
	}
	
    /**
     * How long it takes to use or consume an item
     */
	@Override
    public int getMaxItemUseDuration(ItemStack stack) {
        return 32;
    }
	
	@Override
	public boolean canGoInBook() {
		return false;
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public int getColor(ItemStack stack, int tintIndex) {
		return tintIndex == 0 ? getWarpColor().getColor() : 0xFFFFFFFF;
	}
	
} public class WarpHyper extends Warp {
	
	@Override
	public String getName(World world, ItemStack stack) {
		if (hasValidData(stack)) {
			String name = stack.getTagCompound().getString("hypername");
			if(name != null) {
				return name;
			}
		}
		return unbound;
	}
	
	@Override
	public Waypoint getWaypoint(EntityPlayer player, ItemStack stack) {
		if(hasValidData(stack)) {
			WarpWorldStorage storage = WarpWorldStorage.get(player.getEntityWorld());
			return storage.getWaypoint(stack.getTagCompound().getString("hypername"));
		}
		return null;
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flagIn) {
		tooltip.add(ttprefix + getName(world, stack));
	}
	
	@Override
	public boolean hasValidData(ItemStack stack) {
		return stack.hasTagCompound() && stack.getTagCompound().hasKey("hypername");
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public WarpColors getColor() {
		return WarpColors.HYPER;
	}
	
} public class WarpLocus extends Warp {
	
	@Override
	public String getName(World world, ItemStack stack) {
		if(stack.hasTagCompound() && stack.getTagCompound().hasKey("name")) {
			return stack.getTagCompound().getString("name");
		}
		return unbound;
	}
	
	@Override
	public Waypoint getWaypoint(EntityPlayer player, ItemStack stack) {
		if(hasValidData(stack) ) {
			return new Waypoint("", "",
				stack.getTagCompound().getInteger("posX"),
				stack.getTagCompound().getInteger("posY"),
				stack.getTagCompound().getInteger("posZ"),
				stack.getTagCompound().getInteger("dim"));
		} else {
			return null;
		}
	}
	
	@Override
	public boolean hasValidData(ItemStack stack) {
		return stack.hasTagCompound() &&
				stack.getTagCompound().hasKey("posX") &&
				stack.getTagCompound().hasKey("posY") &&
				stack.getTagCompound().hasKey("posZ") &&
				stack.getTagCompound().hasKey("dim");
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flagIn) {
		tooltip.add(ttprefix + getName(world, stack));
		if(hasValidData(stack)) {
			try {
				tooltip.add(I18n.format("warpbook.bindmsg",
					stack.getTagCompound().getInteger("posX"),
					stack.getTagCompound().getInteger("posY"),
					stack.getTagCompound().getInteger("posZ"),
					stack.getTagCompound().getInteger("dim")));
			}
			catch (Exception e) {}
		}
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public WarpColors getColor() {
		return WarpColors.BOUND;
	}

} public class WarpPlayer extends Warp {

	@Override
	public String getName(World world, ItemStack stack) {
		if (hasValidData(stack)) {
			String name = stack.getTagCompound().getString("player");
			if(name != null) {
				return name;
			}
		}
		return unbound;
	}
	
	@Override
	public Waypoint getWaypoint(EntityPlayer player, ItemStack stack) {

		if (!player.world.isRemote) {
			if(hasValidData(stack)) {
				UUID playerID = UUID.fromString(stack.getTagCompound().getString("playeruuid"));
				EntityPlayerMP playerTo = null;
				List<EntityPlayerMP> allPlayers = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers();
				for (EntityPlayerMP playerS : allPlayers) {
					if (playerS.getUniqueID().equals(playerID)) {
						playerTo = playerS;
					}
				}
				if (player != playerTo && playerTo != null) {
					return new Waypoint("", "",
							MathUtils.round(playerTo.posX, RoundingMode.DOWN),
							MathUtils.round(playerTo.posY, RoundingMode.DOWN),
							MathUtils.round(playerTo.posZ, RoundingMode.DOWN),
							playerTo.dimension);
				}
			}
		}

		return null;
	}
	
	@Override
	public boolean hasValidData(ItemStack stack) {
		return stack.hasTagCompound() && stack.getTagCompound().hasKey("playeruuid");

	}

	@Override
	@SideOnly(Side.CLIENT)
	public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flag) {
		tooltip.add(ttprefix + getName(world, stack));
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public WarpColors getColor() {
		return WarpColors.PLAYER;
	}
	
}
import com.panicnot42.warpbook.item.DeathlyWarpPageItem;
import com.panicnot42.warpbook.item.LegacyWarpPageItem;
import com.panicnot42.warpbook.item.UnboundWarpPageItem;
import com.panicnot42.warpbook.item.UnboundWarpPotionItem;
import com.panicnot42.warpbook.item.WarpBookItem;
import com.panicnot42.warpbook.item.WarpItem;
import com.panicnot42.warpbook.item.WarpPageItem;
import com.panicnot42.warpbook.item.WarpPotionItem;
import com.panicnot42.warpbook.warps.WarpHyper;
import com.panicnot42.warpbook.warps.WarpLocus;
import com.panicnot42.warpbook.warps.WarpPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraftforge.registries.IForgeRegistry;
package com.panicnot42.warpbook;



public class WarpItems {
	
	public WarpBookItem warpBookItem;
	public Item warpClusterItem;
	
	public WarpItem playerWarpPageItem;
	public WarpItem hyperWarpPageItem;
	public WarpItem locusWarpPageItem;
	public WarpItem unboundWarpPageItem;
	public WarpItem legacyPageItem;
	public DeathlyWarpPageItem deathlyWarpPageItem;
	
	public WarpItem unboundWarpPotionItem;
	public WarpItem locusWarpPotionItem;
	public WarpItem playerWarpPotionItem;
	public WarpItem hyperWarpPotionItem;
	
	public WarpItems() {
		
		//Misc
		warpBookItem = new WarpBookItem("warpbook");
		warpClusterItem = new WarpItem("warpcluster");
		
		//Pages
		unboundWarpPageItem = new UnboundWarpPageItem("unboundwarppage");
		locusWarpPageItem = new WarpPageItem("boundwarppage").setWarp(new WarpLocus()).setCloneable(true);