public class BlockATM extends BlockProtected {

	public static final PropertyDirection FACING = BlockHorizontal.FACING;

	public BlockATM() {
		super(Material.IRON);
		setHardness(3.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(30.0F);
		setLightLevel(8);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		world.setBlockState(pos, state.withProperty(FACING, player.getHorizontalFacing().getOpposite()), 2);
		super.onBlockPlacedBy(world, pos, state, player, stack);
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileATM) {
			if (((TileATM) tileEntity).inUse) {
				if (!worldIn.isRemote) {
					playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("chat.warning.inuse")));
				}
				return true;
			} else {
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				((TileATM) tileEntity).playerName = playerIn.getName();
				((TileATM) tileEntity).playerUID = playerIn.getUniqueID().toString();
				((TileATM) tileEntity).inUse = true;
				return true;
			}
		}
		return false;
	}

	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TileATM();
	}

	/**
	 * Convert the given metadata into a BlockState for this Block
	 */
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing enumfacing = EnumFacing.getFront(meta);

		if (enumfacing.getAxis() == EnumFacing.Axis.Y) {
			enumfacing = EnumFacing.NORTH;
		}

		return this.getDefaultState().withProperty(FACING, enumfacing);
	}

	/**
	 * Convert the BlockState into the correct metadata value
	 */
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getIndex();
	}

	/**
	 * Returns the blockstate with the given rotation from the passed
	 * blockstate. If inapplicable, returns the passed blockstate.
	 */
	public IBlockState withRotation(IBlockState state, Rotation rot) {
		return state.withProperty(FACING, rot.rotate((EnumFacing) state.getValue(FACING)));
	}

	/**
	 * Returns the blockstate with the given mirror of the passed blockstate. If
	 * inapplicable, returns the passed blockstate.
	 */
	public IBlockState withMirror(IBlockState state, Mirror mirrorIn) {
		return state.withRotation(mirrorIn.toRotation((EnumFacing) state.getValue(FACING)));
	}

	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] { FACING });
	}
} public class BlockPackager extends BlockProtected {

	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);

	public BlockPackager() {
		super(Material.IRON);
		setHardness(3.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(30.0F);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}

	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TilePackager) {
			if (((TilePackager) tileEntity).inUse) {
				if (!worldIn.isRemote) {
					playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("chat.warning.inuse")));
				}
				return true;
			} else {
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				((TilePackager) tileEntity).playerName = playerIn.getName();
				((TilePackager) tileEntity).inUse = true;
				return true;
			}
		}
		return false;
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TilePackager();
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		world.setBlockState(pos, state.withProperty(FACING, player.getHorizontalFacing().getOpposite()), 2);
		super.onBlockPlacedBy(world, pos, state, player, stack);
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] { FACING });
	}

	/**
	 * Convert the given metadata into a BlockState for this Block
	 */
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing enumfacing = EnumFacing.getFront(meta);

		if (enumfacing.getAxis() == EnumFacing.Axis.Y) {
			enumfacing = EnumFacing.NORTH;
		}

		return this.getDefaultState().withProperty(FACING, enumfacing);
	}

	/**
	 * Convert the BlockState into the correct metadata value
	 */
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getIndex();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TilePackager te = world.getTileEntity(pos) instanceof TilePackager ? (TilePackager) world.getTileEntity(pos)
				: null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class BlockPowerReceiver extends BlockProtected {

	public BlockPowerReceiver() {
		super(Material.IRON);
		setHardness(3.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(30.0F);
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		super.onBlockPlacedBy(world, pos, state, player, stack);
		if (world.isRemote)
			return;
		TileEntity te = world.getTileEntity(pos);
		if (te instanceof TilePowerReceiver) {
			TilePowerReceiver tentity = (TilePowerReceiver) te;
			tentity.blockOwner = player.getName();
		}
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity te = worldIn.getTileEntity(pos);
		if (te != null && te instanceof TilePowerReceiver) {
			TilePowerReceiver tentity = (TilePowerReceiver) te;
			if (tentity.publicAccess || playerIn.getName().matches(tentity.blockOwner)) {
				tentity.blockOwner = playerIn.getName();
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				return true;
			}
			if (!worldIn.isRemote) {
				playerIn.sendMessage(new TextComponentTranslation("chat.warning.private"));
			}
		}
		return false;
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TilePowerReceiver();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TilePowerReceiver te = world.getTileEntity(pos) instanceof TilePowerReceiver
				? (TilePowerReceiver) world.getTileEntity(pos)
				: null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class BlockPowerTransmitter extends BlockProtected {

	public BlockPowerTransmitter() {
		super(Material.IRON);
		setHardness(3.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(30.0F);
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		super.onBlockPlacedBy(world, pos, state, player, stack);
		if (world.isRemote)
			return;
		TileEntity te = world.getTileEntity(pos);
		if (te instanceof TilePowerTransmitter) {
			TilePowerTransmitter tentity = (TilePowerTransmitter) te;
			tentity.blockOwner = player.getName();
		}
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity te = worldIn.getTileEntity(pos);
		if (te != null && te instanceof TilePowerTransmitter) {
			TilePowerTransmitter tentity = (TilePowerTransmitter) te;
			if (tentity.publicAccess || playerIn.getName().matches(tentity.blockOwner)) {
				tentity.blockOwner = playerIn.getName();
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				return true;
			}
			if (!worldIn.isRemote) {
				playerIn.sendMessage(new TextComponentTranslation("chat.warning.private"));
			}
		}
		return false;
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TilePowerTransmitter();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TilePowerTransmitter te = world.getTileEntity(pos) instanceof TilePowerTransmitter
				? (TilePowerTransmitter) world.getTileEntity(pos)
				: null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class BlockSafe extends BlockProtected {

	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);

	public BlockSafe() {
		super(Material.IRON);
		setHardness(3.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(30.0F);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileSafe) {
			TileSafe tentity = (TileSafe) tileEntity;
			if (playerIn.getName().matches(tentity.blockOwner)) {
				if (!worldIn.isRemote)
					tentity.updateAccountBalance();
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
			}
		}
		return true;
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		if (world.isRemote)
			return;
		world.setBlockState(pos, state.withProperty(FACING, player.getHorizontalFacing().getOpposite()), 2);
		TileEntity tileEntity = world.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileSafe) {
			TileSafe tentity = (TileSafe) tileEntity;
			tentity.blockOwner = player.getName();
			tentity.setSafeAccount(player.getName());
		}
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TileSafe();
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	@Override
	public void onBlockExploded(World world, BlockPos pos, Explosion explosion) {
		world.setBlockToAir(pos);
		onBlockDestroyedByExplosion(world, pos, explosion);
		EntityItem entityItem = new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(this, 1));
		if (!world.isRemote)
			world.spawnEntity(entityItem);
	}

	/**
	 * Convert the given metadata into a BlockState for this Block
	 */
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing enumfacing = EnumFacing.getFront(meta);

		if (enumfacing.getAxis() == EnumFacing.Axis.Y) {
			enumfacing = EnumFacing.NORTH;
		}

		return this.getDefaultState().withProperty(FACING, enumfacing);
	}

	/**
	 * Convert the BlockState into the correct metadata value
	 */
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getIndex();
	}

	/**
	 * Returns the blockstate with the given rotation from the passed
	 * blockstate. If inapplicable, returns the passed blockstate.
	 */
	public IBlockState withRotation(IBlockState state, Rotation rot) {
		return state.withProperty(FACING, rot.rotate((EnumFacing) state.getValue(FACING)));
	}

	/**
	 * Returns the blockstate with the given mirror of the passed blockstate. If
	 * inapplicable, returns the passed blockstate.
	 */
	public IBlockState withMirror(IBlockState state, Mirror mirrorIn) {
		return state.withRotation(mirrorIn.toRotation((EnumFacing) state.getValue(FACING)));
	}

	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] { FACING });
	}
} public class BlockSignal extends BlockProtected {

	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);

	public BlockSignal() {
		super(Material.IRON);
		setHardness(3.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(30.0F);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (playerIn.isSneaking()) {
			TileEntity te = worldIn.getTileEntity(pos);
			if (te != null && te instanceof TileSignal) {
				TileSignal tentity = (TileSignal) te;
				if (playerIn.getCommandSenderEntity().getName().matches(tentity.blockOwner)) {
					playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				}
			}
		} else {
			// take coins and activate on click
			NonNullList<ItemStack> inventory = playerIn.inventory.mainInventory;
			TileSignal tentity = (TileSignal) worldIn.getTileEntity(pos);
			int coinsFound = 0;
			for (int i = 0; i < playerIn.inventory.getSizeInventory(); i++) {
				ItemStack stack = playerIn.inventory.getStackInSlot(i);
				if (stack != null) {
					switch (stack.getItem().getUnlocalizedName()) {
					case "item.universalcoins.iron_coin":
						coinsFound += stack.getCount() * UniversalCoins.coinValues[0];
						playerIn.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
						break;
					case "item.universalcoins.gold_coin":
						coinsFound += stack.getCount() * UniversalCoins.coinValues[1];
						playerIn.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
						break;
					case "item.universalcoins.emerald_coin":
						coinsFound += stack.getCount() * UniversalCoins.coinValues[2];
						playerIn.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
						break;
					case "item.universalcoins.diamond_coin":
						coinsFound += stack.getCount() * UniversalCoins.coinValues[3];
						playerIn.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
						break;
					case "item.universalcoins.obsidian_coin":
						coinsFound += stack.getCount() * UniversalCoins.coinValues[4];
						playerIn.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
						break;
					}
				}
				if (coinsFound > tentity.fee)
					break;
			}
			if (worldIn.isRemote)
				return true; // we don't want to do the rest on client side
			if (coinsFound < tentity.fee) {
				playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("signal.message.notenough")));
			} else {
				// we have enough coins to cover the fee so we pay it and
				// return
				// the change
				playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("signal.message.activated")));
				coinsFound -= tentity.fee;
				tentity.activateSignal();
			}
			ItemStack stack = null;
			while (coinsFound > 0) {
				if (coinsFound >= UniversalCoins.coinValues[4]) {
					stack = new ItemStack(UniversalCoins.Items.obsidian_coin, 1);
					stack.setCount((int) Math.floor(coinsFound / UniversalCoins.coinValues[4]));
					coinsFound -= stack.getCount() * UniversalCoins.coinValues[4];
				} else if (coinsFound >= UniversalCoins.coinValues[3]) {
					stack = new ItemStack(UniversalCoins.Items.diamond_coin, 1);
					stack.setCount((int) Math.floor(coinsFound / UniversalCoins.coinValues[3]));
					coinsFound -= stack.getCount() * UniversalCoins.coinValues[3];
				} else if (coinsFound >= UniversalCoins.coinValues[2]) {
					stack = new ItemStack(UniversalCoins.Items.emerald_coin, 1);
					stack.setCount((int) Math.floor(coinsFound / UniversalCoins.coinValues[2]));
					coinsFound -= stack.getCount() * UniversalCoins.coinValues[2];
				} else if (coinsFound >= UniversalCoins.coinValues[1]) {
					stack = new ItemStack(UniversalCoins.Items.gold_coin, 1);
					stack.setCount((int) Math.floor(coinsFound / UniversalCoins.coinValues[1]));
					coinsFound -= stack.getCount() * UniversalCoins.coinValues[1];
				} else if (coinsFound >= UniversalCoins.coinValues[0]) {
					stack = new ItemStack(UniversalCoins.Items.iron_coin, 1);
					stack.setCount((int) Math.floor(coinsFound / UniversalCoins.coinValues[0]));
					coinsFound -= stack.getCount() * UniversalCoins.coinValues[0];
				}
				if (stack == null)
					break;
				// add a stack to the players inventory
				if (playerIn.inventory.getFirstEmptyStack() != -1) {
					playerIn.inventory.addItemStackToInventory(stack);
				} else {
					for (int j = 0; j < playerIn.inventory.getSizeInventory(); j++) {
						ItemStack istack = playerIn.inventory.getStackInSlot(j);
						if (istack != null && istack.getItem() == stack.getItem()) {
							int amountToAdd = (int) Math.min(stack.getCount(),
									istack.getMaxStackSize() - istack.getCount());
							istack.setCount(istack.getCount() + amountToAdd);
							stack.setCount(stack.getCount() - amountToAdd);
						}
					}
					if (stack.getCount() > 0) {
						// at this point, we're going to throw extra to the
						// world since
						// the player inventory must be full.
						Random rand = new Random();
						float rx = rand.nextFloat() * 0.8F + 0.1F;
						float ry = rand.nextFloat() * 0.8F + 0.1F;
						float rz = rand.nextFloat() * 0.8F + 0.1F;
						EntityItem entityItem = new EntityItem(worldIn, ((EntityPlayerMP) playerIn).posX + rx,
								((EntityPlayerMP) playerIn).posY + ry, ((EntityPlayerMP) playerIn).posZ + rz, stack);
						worldIn.spawnEntity(entityItem);
					}
				}
			}
		}
		return true;

	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		world.setBlockState(pos, state.withProperty(FACING, player.getHorizontalFacing().getOpposite()), 2);
		super.onBlockPlacedBy(world, pos, state, player, stack);
		if (world.isRemote)
			return;
		TileEntity te = world.getTileEntity(pos);
		if (te instanceof TileSignal) {
			TileSignal tentity = (TileSignal) te;
			tentity.blockOwner = player.getName();
		}
	}

	public void updatePower(World worldIn, BlockPos pos) {
		if (!worldIn.isRemote) {
			worldIn.notifyNeighborsOfStateChange(pos, this, true);
			EnumFacing[] aenumfacing = EnumFacing.values();
			int i = aenumfacing.length;

			for (int j = 0; j < i; ++j) {
				EnumFacing enumfacing = aenumfacing[j];
				worldIn.notifyNeighborsOfStateChange(pos.offset(enumfacing), this, true);
			}
		}
	}

	@Override
	public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing side) {
		TileEntity te = blockAccess.getTileEntity(pos);
		if (te != null && te instanceof TileSignal) {
			TileSignal tentity = (TileSignal) te;
			return tentity.canProvidePower ? 15 : 0;
		}
		return 0;
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TileSignal();
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	@Override
	public boolean canProvidePower(IBlockState state) {
		return true;
	}

	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] { FACING });
	}

	/**
	 * Convert the given metadata into a BlockState for this Block
	 */
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing enumfacing = EnumFacing.getFront(meta);

		if (enumfacing.getAxis() == EnumFacing.Axis.Y) {
			enumfacing = EnumFacing.NORTH;
		}

		return this.getDefaultState().withProperty(FACING, enumfacing);
	}

	/**
	 * Convert the BlockState into the correct metadata value
	 */
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getIndex();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TileSignal te = world.getTileEntity(pos) instanceof TileSignal ? (TileSignal) world.getTileEntity(pos) : null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class BlockTradeStation extends BlockProtected {

	public BlockTradeStation() {
		super(Material.IRON);
		setHardness(3.0f);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setResistance(6000.0F);
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		super.onBlockPlacedBy(world, pos, state, player, stack);
		if (world.isRemote)
			return;
		TileEntity te = world.getTileEntity(pos);
		if (te instanceof TileTradeStation) {
			TileTradeStation tentity = (TileTradeStation) te;
			tentity.blockOwner = player.getName();
			if (stack.hasDisplayName()) {
				tentity.setName(stack.getDisplayName());
			}
		}

	}

	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileTradeStation) {
			TileTradeStation tentity = (TileTradeStation) tileEntity;
			if (tentity.inUse) {
				if (!worldIn.isRemote) {
					playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("chat.warning.inuse")));
				}
				return true;
			}
			if (tentity.publicAccess) {
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				tentity.playerName = playerIn.getName();
				tentity.inUse = true;
				return true;
			} else {
				if (tentity.blockOwner.matches(playerIn.getName())) {
					playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
					tentity.playerName = playerIn.getName();
					tentity.inUse = true;
					return true;
				}
				if (!worldIn.isRemote) {
					playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("chat.warning.private")));
				}
			}
		}
		return false;
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	@Override
	public TileEntity createNewTileEntity(World worldIn, int meta) {
		return new TileTradeStation();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TileTradeStation te = world.getTileEntity(pos) instanceof TileTradeStation
				? (TileTradeStation) world.getTileEntity(pos)
				: null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class BlockUCStandingSign extends BlockStandingSign {

	private Class signEntityClass;
	private boolean isStanding;

	public BlockUCStandingSign(Class tileEntity) {
		super();
		this.isStanding = true;
		this.signEntityClass = tileEntity;
		float f = 0.25F;
		float f1 = 1.0F;
		this.setDefaultState(this.blockState.getBaseState().withProperty(ROTATION, Integer.valueOf(0)));
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.INVISIBLE;
	}

	@Override
	@SideOnly(Side.CLIENT)
	public AxisAlignedBB getSelectedBoundingBox(IBlockState blockState, World worldIn, BlockPos pos) {
		this.getBoundingBox(blockState, worldIn, pos);
		return super.getSelectedBoundingBox(blockState, worldIn, pos);
	}

	@Override
	public TileEntity createNewTileEntity(World world, int p_149915_2_) {
		try {
			return (TileUCSign) this.signEntityClass.newInstance();
		} catch (Exception exception) {
			throw new RuntimeException(exception);
		}
	}

	@Override
	public void onBlockClicked(World world, BlockPos pos, EntityPlayer player) {
		String ownerName = ((TileUCSign) world.getTileEntity(pos)).blockOwner;
		if (player.getDisplayName().toString().matches(ownerName)) {
			this.setHardness(1.0F);
		} else {
			this.setHardness(-1.0F);
		}
	}

	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileUCSign) {
			TileUCSign tentity = (TileUCSign) tileEntity;
			if (playerIn.getName().matches(tentity.blockOwner)) {
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player,
			boolean willHarvest) {
		String ownerName = ((TileUCSign) world.getTileEntity(pos)).blockOwner;
		if (player.capabilities.isCreativeMode) {
			super.removedByPlayer(state, world, pos, player, willHarvest);
			return true;
		}
		if (player.getDisplayName().toString().matches(ownerName) && !world.isRemote) {
			super.removedByPlayer(state, world, pos, player, willHarvest);
			return true;
		}
		return false;
	}

	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune) {
		return UniversalCoins.Items.uc_sign;
	}
} public class BlockUCWallSign extends BlockWallSign {

	private Class signEntityClass;
	private boolean isStanding;

	public BlockUCWallSign(Class tileEntity) {
		super();
		this.isStanding = false;
		this.signEntityClass = tileEntity;
		float f = 0.25F;
		float f1 = 1.0F;
		// this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f1, 0.5F +
		// f);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.INVISIBLE;
	}

	@Override
	@SideOnly(Side.CLIENT)
	public AxisAlignedBB getSelectedBoundingBox(IBlockState blockState, World worldIn, BlockPos pos) {
		this.getBoundingBox(blockState, worldIn, pos);
		return super.getSelectedBoundingBox(blockState, worldIn, pos);
	}

	@Override
	public TileEntity createNewTileEntity(World world, int p_149915_2_) {
		try {
			return (TileUCSign) this.signEntityClass.newInstance();
		} catch (Exception exception) {
			throw new RuntimeException(exception);
		}
	}

	@Override
	public void onBlockClicked(World world, BlockPos pos, EntityPlayer player) {
		if (UniversalCoins.blockProtection) {
			String ownerName = ((TileUCSign) world.getTileEntity(pos)).blockOwner;
			if (player.getDisplayName().toString().matches(ownerName)) {
				this.setHardness(1.0F);
			} else {
				this.setHardness(-1.0F);
			}
		}
	}

	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileUCSign) {
			TileUCSign tentity = (TileUCSign) tileEntity;
			if (playerIn.getName().matches(tentity.blockOwner)) {
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player,
			boolean willHarvest) {
		String ownerName = ((TileUCSign) world.getTileEntity(pos)).blockOwner;
		if (player.capabilities.isCreativeMode) {
			super.removedByPlayer(state, world, pos, player, willHarvest);
			return true;
		}
		if (player.getName().contentEquals(ownerName) && !world.isRemote) {
			super.removedByPlayer(state, world, pos, player, willHarvest);
			return true;
		}
		return false;
	}

	@Override
	public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) {
		EnumFacing enumfacing = (EnumFacing) state.getValue(FACING);
		TileEntity tileEntity = worldIn.getTileEntity(pos);

		if (tileEntity != null && tileEntity instanceof TileUCSign) {
			((TileUCSign) tileEntity).scanChestContents(state, fromPos);
		}
	}

	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune) {
		return UniversalCoins.Items.uc_sign;
	}
} public class BlockVendor extends BlockProtected {

	protected static final AxisAlignedBB DEFAULT_AABB = new AxisAlignedBB(0.0625f, 0.125f, 0.0625f, 0.9375f, 0.9375f,
			0.9375f);

	public BlockVendor() {
		super(Material.IRON);
		// setStepSound(stepSound.GLASS);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		setHardness(0.3F);
		setResistance(6000.0F);
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	@SideOnly(Side.CLIENT)
	public BlockRenderLayer getBlockLayer() {
		return BlockRenderLayer.CUTOUT;
	}

	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}

	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		return DEFAULT_AABB;
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		super.onBlockPlacedBy(world, pos, state, player, stack);
		if (world.isRemote)
			return;
		TileEntity te = world.getTileEntity(pos);
		if (te instanceof TileVendor) {
			TileVendor tentity = (TileVendor) te;
			tentity.blockOwner = player.getName();
		}
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileVendor) {
			TileVendor tentity = (TileVendor) tileEntity;
			if (tentity.inUse) {
				if (!worldIn.isRemote) {
					playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("chat.warning.inuse")));
				}
				return true;
			} else {
				tentity.update();
				tentity.playerName = playerIn.getName();
				tentity.inUse = true;
				tentity.updateCoinsForPurchase();
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				return true;
			}
		}
		return false;
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TileVendorBlock();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TileVendor te = world.getTileEntity(pos) instanceof TileVendor ? (TileVendor) world.getTileEntity(pos)
				: null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class BlockVendorFrame extends BlockProtected {

	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
	protected static final AxisAlignedBB FRAME_NORTH_AABB = new AxisAlignedBB(0.12f, 0.12f, 0f, 0.88f, 0.88f, 0.07f);
	protected static final AxisAlignedBB FRAME_SOUTH_AABB = new AxisAlignedBB(0.12f, 0.12f, 0.93f, 0.88f, 0.88f, 1.00f);
	protected static final AxisAlignedBB FRAME_EAST_AABB = new AxisAlignedBB(0.93f, 0.12f, 0.12f, 1.0f, 0.88f, 0.88f);
	protected static final AxisAlignedBB FRAME_WEST_AABB = new AxisAlignedBB(0.07f, 0.12f, 0.12f, 0f, 0.88f, 0.88f);

	public BlockVendorFrame() {
		super(Material.WOOD);
		setHardness(1.0f);
		setResistance(6000.0F);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}

	@Override
	public boolean isOpaqueCube(IBlockState state) {
		return false;
	}

	@Override
	public boolean isFullCube(IBlockState state) {
		return false;
	}

	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) {
		return EnumBlockRenderType.MODEL;
	}

	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
		switch (state.getValue(FACING)) {
		case EAST:
			return FRAME_EAST_AABB;
		case WEST:
			return FRAME_WEST_AABB;
		case SOUTH:
			return FRAME_SOUTH_AABB;
		case NORTH:
		default:
			return FRAME_NORTH_AABB;
		}
	}

	public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase player,
			ItemStack stack) {
		world.setBlockState(pos, state.withProperty(FACING, player.getHorizontalFacing()), 2);
		super.onBlockPlacedBy(world, pos, state, player, stack);
		if (world.isRemote)
			return;
		TileEntity te = world.getTileEntity(pos);
		if (te instanceof TileVendorFrame) {
			TileVendorFrame tentity = (TileVendorFrame) te;
			tentity.blockOwner = player.getName();
		}
	}

	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		TileEntity tileEntity = worldIn.getTileEntity(pos);
		if (tileEntity != null && tileEntity instanceof TileVendor) {
			TileVendor tentity = (TileVendor) tileEntity;
			if (tentity.inUse) {
				if (!worldIn.isRemote) {
					playerIn.sendMessage(new TextComponentString(I18n.translateToLocal("chat.warning.inuse")));
				}
				return true;
			} else {
				tentity.updateTE();
				tentity.playerName = playerIn.getName();
				tentity.inUse = true;
				playerIn.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
				return true;
			}
		}
		return false;
	}

	@Override
	public TileEntity createNewTileEntity(World var1, int var2) {
		return new TileVendorFrame();
	}

	protected BlockStateContainer createBlockState() {
		return new BlockStateContainer(this, new IProperty[] { FACING });
	}

	/**
	 * Convert the given metadata into a BlockState for this Block
	 */
	public IBlockState getStateFromMeta(int meta) {
		EnumFacing enumfacing = EnumFacing.getFront(meta);

		if (enumfacing.getAxis() == EnumFacing.Axis.Y) {
			enumfacing = EnumFacing.NORTH;
		}

		return this.getDefaultState().withProperty(FACING, enumfacing);
	}

	/**
	 * Convert the BlockState into the correct metadata value
	 */
	public int getMetaFromState(IBlockState state) {
		return ((EnumFacing) state.getValue(FACING)).getIndex();
	}

	@Override
	public void getDrops(net.minecraft.util.NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos,
			IBlockState state, int fortune) {
		TileVendorFrame te = world.getTileEntity(pos) instanceof TileVendorFrame
				? (TileVendorFrame) world.getTileEntity(pos)
				: null;
		ItemStack stack = new ItemStack(Item.getItemFromBlock(this));
		if (te != null) {
			NBTTagCompound tag = new NBTTagCompound();
			te.writeToNBT(tag);
			stack.setTagInfo("BlockEntityTag", tag);
		}
		drops.add(stack);
	}
} public class UCBalance extends CommandBase implements ICommand {

	@Override
	public String getName() {
		return "balance";
	}

	@Override
	public String getUsage(ICommandSender var1) {
		return "/balance : returns player inventory and account coin balances";
	}

	@Override
	public boolean checkPermission(MinecraftServer server, ICommandSender sender) {
		return true;
	}

	@Override
	public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
		if (sender instanceof EntityPlayerMP) {
			int playerCoins = getPlayerCoins((EntityPlayerMP) sender);
			String uuid = ((EntityPlayerMP) sender).getPersistentID().toString();
			String playerAcct = UniversalAccounts.getInstance().getPlayerAccount(uuid);
			long accountBalance = UniversalAccounts.getInstance().getAccountBalance(playerAcct);
			DecimalFormat formatter = new DecimalFormat("#,###,###,###,###,###,###");
			sender.sendMessage(new TextComponentString("Inventory: " + formatter.format(playerCoins)));
			//TODO change translation strings
			//player.sendMessage(new TextComponentTranslation("text.message"));
			if (accountBalance != -1) {
				sender.sendMessage(new TextComponentString("Account: " + formatter.format(accountBalance)));
			}
			
			// achievement stuff		
//			if (accountBalance > 1000) {
//				((EntityPlayerMP) sender).addStat(Achievements.achThousand, 1);
//			}
//			if (accountBalance > 1000000) {
//				((EntityPlayerMP) sender).addStat(Achievements.achMillion, 1);
//			}
//			if (accountBalance > 1000000000) {
//				((EntityPlayerMP) sender).addStat(Achievements.achBillion, 1);
//			}
//			if (accountBalance > 1000000000000) {
//				((EntityPlayerMP) sender).addStat(Achievements.achTrillion, 1);
//			}
//			if (accountBalance > 1000000000000000) {
//				((EntityPlayerMP) sender).addStat(Achievements.achQuadrillion, 1);
//			}
//			if (accountBalance > 1000000000000000000) {
//					((EntityPlayerMP) sender).addStat(Achievements.achQuintillion, 1);
//				}
//			if (playerCoins == Long.MAX_VALUE || accountBalance == Long.MAX_VALUE) {
//				((EntityPlayerMP) sender).addStat(Achievements.achMaxed, 1);
//			}
		}
	}

	private int getPlayerCoins(EntityPlayerMP player) {
		int coinsFound = 0;
		for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
			ItemStack stack = player.inventory.getStackInSlot(i);
			if (stack != null) {
				switch (stack.getUnlocalizedName()) {
				case "item.universalcoins.iron_coin":
					coinsFound += stack.getCount() * UniversalCoins.coinValues[0];
					break;
				case "item.universalcoins.gold_coin":
					coinsFound += stack.getCount() * UniversalCoins.coinValues[1];
					break;
				case "item.universalcoins.emerald_coin":
					coinsFound += stack.getCount() * UniversalCoins.coinValues[2];
					break;
				case "item.universalcoins.diamond_coin":
					coinsFound += stack.getCount() * UniversalCoins.coinValues[3];
					break;
				case "item.universalcoins.obsidian_coin":
					coinsFound += stack.getCount() * UniversalCoins.coinValues[4];
					break;
				}
			}
		}
		return coinsFound;
	}
} public class UCCommand extends CommandBase implements ICommand {
	DecimalFormat formatter = new DecimalFormat("#,###,###,###,###,###,###");

	@Override
	public String getName() {
		return "universalcoins";
	}

	@Override
	public String getUsage(ICommandSender icommandsender) {
		return "/universalcoins help";
	}

	@Override
	public List<String> getAliases() {
		List<String> aliases = new ArrayList<String>();
		aliases.add("uc");
		return aliases;
	}

	// Method called when the command is typed in
	@Override
	public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
		if (args.length <= 0) {
			throw new WrongUsageException(this.getUsage(sender));
		} else if (args[0].matches("help")) {
			sender.sendMessage(new TextComponentString("Usage: /uc <command option> <arguments>"));
			sender.sendMessage(new TextComponentString("Available command options:"));
			sender.sendMessage(new TextComponentString("/uc get : Get price of item held in main hand."));
			sender.sendMessage(new TextComponentString("/uc set <price> : Set price of item held in main hand."));
			sender.sendMessage(
					new TextComponentString("/uc reload : Reload pricelists. This will reset any unsaved changes."));
			sender.sendMessage(new TextComponentString(
					"/uc reset : Reset all prices to defaults. Will not override items not priced by default"));
			sender.sendMessage(new TextComponentString("/uc save : Save pricelists."));
			sender.sendMessage(new TextComponentString("/uc update : rerun auto-pricing"));
		} else if (args[0].matches("reload")) {
			UCItemPricer.getInstance().loadConfigs();
		} else if (args[0].matches("get")) {
			// get item price
			if (args.length == 1) {
				int price = -1;
				String stackName = "";
				ItemStack stack = getPlayerItem(sender);
				if (stack != null) {
					price = UCItemPricer.getInstance().getItemPrice(stack);
					stackName = getPlayerItem(sender).getDisplayName();
				} else {
					sender.sendMessage(new TextComponentString("§cError: no item found in hand."));
				}

				if (price == -1) {
					sender.sendMessage(new TextComponentString("§cNo price set for" + " " + stackName));
				} else
					sender.sendMessage(new TextComponentString("§a" + stackName + " = " + formatter.format(price)));
			}
		} else if (args[0].matches("set")) {
			// set item price
			if (args.length > 1) {
				boolean result = false;
				int price = -1;
				try {
					price = Integer.parseInt(args[1]);
				} catch (NumberFormatException e) {
					sender.sendMessage(new TextComponentString("§cError: invalid price"));
					return;
				}
				ItemStack stack = getPlayerItem(sender);
				if (stack != null) {
					result = UCItemPricer.getInstance().setItemPrice(stack, price);
				}

				if (result == true) {
					sender.sendMessage(new TextComponentString("Price set to " + formatter.format(price)));
				} else {
					sender.sendMessage(new TextComponentString("§cFailed to set price."));
				}
			} else
				sender.sendMessage(new TextComponentString("Please specify price."));
		} else if (args[0].matches("reload")) {
			UCItemPricer.getInstance().loadConfigs();
			sender.sendMessage(new TextComponentString("§aAll changes since last save have been reset."));
		} else if (args[0].matches("reset")) {
			UCItemPricer.getInstance().resetDefaults();
			sender.sendMessage(new TextComponentString("§aPrice defaults reloaded."));
		} else if (args[0].matches("save")) {
			UCItemPricer.getInstance().savePriceLists();
			sender.sendMessage(new TextComponentString("§aChanges will be saved."));
		} else if (args[0].matches("update")) {
			UCItemPricer.getInstance().updatePriceLists();
			sender.sendMessage(new TextComponentString("§aPrices updated."));
		}
	}

	private ItemStack getPlayerItem(ICommandSender sender) {
		EntityPlayer player = (EntityPlayer) sender;
		if (player.getHeldItemMainhand() != null) {
			ItemStack stack = player.getHeldItemMainhand();
			return stack;
		}
		return null;
	}

	@Override
	public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) {
		if (args.length == 1) {
			List<String> options = new ArrayList<String>();
			options.add("help");
			options.add("get");
			options.add("set");
			options.add("reload");
			options.add("reset");
			options.add("save");
			options.add("update");
			return getListOfStringsMatchingLastWord(args, options);
		}
		return null;
	}
} public class UCGive extends UCCommandBase implements ICommand {

	@Override
	public String getName() {
		return "givecoins";
	}

	@Override
	public String getUsage(ICommandSender var1) {
		return "/givecoins <player> <amount>";
	}

	@Override
	public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
		if (args.length == 2) {
			EntityPlayer recipient = null;
			WorldServer[] ws = server.worlds;
			for (WorldServer w : ws) {
				if (w.playerEntities.contains(w.getPlayerEntityByName(args[0]))) {
					recipient = (EntityPlayer) w.getPlayerEntityByName(args[0]);
				}
			}
			int coinsToSend = 0;
			if (recipient == null) {
				sender.sendMessage(new TextComponentString("§cPlayer not found!"));
				return;
			}
			try {
				coinsToSend = Integer.parseInt(args[1]);
			} catch (NumberFormatException e) {
				sender.sendMessage(new TextComponentString("§cInvalid coin amount!"));
				return;
			}
			if (coinsToSend <= 0) {
				sender.sendMessage(new TextComponentString("§cInvalid coin amount!"));
				return;
			}
			// we made it through the exceptions, give the coins to the player
			givePlayerCoins(recipient, coinsToSend);
			DecimalFormat formatter = new DecimalFormat("#,###,###,###,###,###,###");
			sender.sendMessage(
					new TextComponentString("Gave " + args[0] + " " + formatter.format(coinsToSend) + " Coin."));
			recipient.sendMessage(new TextComponentString(sender.getName() + " gave you " + (coinsToSend) + " coin."));
		} else
			sender.sendMessage(new TextComponentString("§cError: Please specify recipient and amount."));
	}

	@Override
	public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) {
		if (args.length == 1) {
			List<String> players = new ArrayList<String>();
			for (EntityPlayer p : (List<EntityPlayer>) sender.getEntityWorld().playerEntities) {
				players.add(p.getName());
			}
			return getListOfStringsMatchingLastWord(args, players);
		}
		return null;
	}
} public class UCRebalance extends UCCommandBase implements ICommand {

	@Override
	public String getName() {
		return "rebalance";
	}

	@Override
	public String getUsage(ICommandSender var1) {
		return "/rebalance : consolidates inventory coins into largest values possible";
	}

	@Override
	public boolean checkPermission(MinecraftServer server, ICommandSender sender) {
		return true;
	}

	@Override
	public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
		if (sender instanceof EntityPlayerMP) {
			if (args.length == 0) {
				// get coins from player inventory
				int coinsFound = 0;
				EntityPlayerMP player = (EntityPlayerMP) sender;
				for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
					ItemStack stack = player.inventory.getStackInSlot(i);
					if (stack != null) {
						switch (stack.getUnlocalizedName()) {
						case "item.universalcoins.iron_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[0];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.gold_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[1];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.emerald_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[2];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.diamond_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[3];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.obsidian_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[4];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						}
					}
				}
				// give coins back to player
				givePlayerCoins(player, coinsFound);
			}
		}
	}
} public class UCSend extends UCCommandBase implements ICommand {

	@Override
	public String getName() {
		return "send";
	}

	@Override
	public List<String> getAliases() {
		List<String> aliases = new ArrayList<String>();
		aliases.add("pay");
		return aliases;
	}

	@Override
	public String getUsage(ICommandSender var1) {
		return "/send <playername> <amount> : send another player coins from your inventory";
	}

	@Override
	public boolean checkPermission(MinecraftServer server, ICommandSender sender) {
		return true;
	}

	@Override
	public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
		if (sender instanceof EntityPlayerMP) {
			if (args.length == 2) {
				// check for player
				EntityPlayerMP recipient = null;
				WorldServer[] ws = server.worlds;
				for (WorldServer w : ws) {
					if (w.playerEntities.contains(w.getPlayerEntityByName(args[0]))) {
						recipient = (EntityPlayerMP) w.getPlayerEntityByName(args[0]);
					}
				}
				if (recipient == null) {
					sender.sendMessage(new TextComponentString("§cError: player not found"));
					return;
				}
				int requestedSendAmount = 0;
				try {
					requestedSendAmount = Integer.parseInt(args[1]);
				} catch (NumberFormatException e) {
					sender.sendMessage(new TextComponentString("§cError: invalid number format"));
					return;
				}
				if (requestedSendAmount <= 0) {
					sender.sendMessage(new TextComponentString("§cError: specify an amount greater than zero"));
					return;
				}
				// get coins from player inventory
				int coinsFound = 0;
				EntityPlayerMP player = (EntityPlayerMP) sender;
				for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
					ItemStack stack = player.inventory.getStackInSlot(i);
					if (stack != null) {
						switch (stack.getUnlocalizedName()) {
						case "item.universalcoins.iron_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[0];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.gold_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[1];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.emerald_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[2];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.diamond_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[3];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						case "item.universalcoins.obsidian_coin":
							coinsFound += stack.getCount() * UniversalCoins.coinValues[4];
							player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
							break;
						}
					}
				}
				// if sender is short, cancel this transaction and return coins.
				if (coinsFound < requestedSendAmount) {
					sender.sendMessage(new TextComponentString("§cError: insufficent coins."));
					givePlayerCoins((EntityPlayerMP) sender, coinsFound);
					return;
				}
				// subtract coins to send from player coins
				coinsFound -= requestedSendAmount;
				// send coins to recipient
				givePlayerCoins(recipient, requestedSendAmount);
				sender.sendMessage(new TextComponentString(requestedSendAmount + " coin sent to " + " " + args[0]));
				recipient.sendMessage(
						new TextComponentString(requestedSendAmount + " coin sent to you from " + sender.getName()));
				// give sender back change
				givePlayerCoins(player, coinsFound);
			} else
				sender.sendMessage(new TextComponentString("§cPlease specify recipient and amount."));
		}
	}

	@Override
	public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos pos) {
		if (args.length == 1) {
			List<String> players = new ArrayList<String>();
			for (EntityPlayer p : (List<EntityPlayer>) sender.getEntityWorld().playerEntities) {
				players.add(p.getName());
			}
			return getListOfStringsMatchingLastWord(args, players);
		}
		return null;
	}
} public class ItemCatalog extends Item {

	public ItemCatalog() {
		super();
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
		this.setMaxStackSize(1);
	}
} @SuppressWarnings("deprecation")
public class ItemCoin extends Item {

	public ItemCoin() {
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		DecimalFormat formatter = new DecimalFormat("###,###,###,###,###");
		tooltip.add(formatter.format(stack.getCount() * UniversalCoins.coinValues[0]) + " "
				+ (stack.getCount() * UniversalCoins.coinValues[0] > 1
						? I18n.translateToLocal("general.currency.multiple")
						: I18n.translateToLocal("general.currency.single")));
	}
} public class ItemEnderCard extends ItemUCCard {

	@Override
	public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
			EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (!player.getHeldItem(hand).hasTagCompound())
			createNBT(player.getHeldItem(hand), worldIn, player);
		DecimalFormat formatter = new DecimalFormat("#,###,###,###");
		NonNullList<ItemStack> inventory = player.inventory.mainInventory;
		String accountNumber = player.getActiveItemStack().getTagCompound().getString("Account");
		long accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
		int coinValue = 0;
		int depositAmount = 0;
		int coinsDeposited = 0;
		for (int i = 0; i < inventory.size(); i++) {
			ItemStack instack = player.inventory.getStackInSlot(i);
			coinValue = CoinUtils.getCoinValue(instack);
			if (accountBalance == -1)
				// get out of here if the card is invalid
				return EnumActionResult.SUCCESS;
			if (coinValue == 0)
				continue;
			if (Long.MAX_VALUE - accountBalance > coinValue * instack.getCount()) {
				depositAmount = instack.getCount();
			} else {
				depositAmount = (int) (Long.MAX_VALUE - accountBalance) / coinValue;
			}
			UniversalAccounts.getInstance().creditAccount(accountNumber, coinValue * depositAmount, false);
			coinsDeposited += coinValue * depositAmount;
			inventory.get(i).shrink(depositAmount);
			if (inventory.get(i).getCount() == 0) {
				player.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
				player.inventoryContainer.detectAndSendChanges();
			}
		}
		if (coinsDeposited > 0) {
			player.sendMessage(new TextComponentString(I18n.translateToLocal("item.card.deposit") + " "
					+ formatter.format(coinsDeposited) + " " + I18n.translateToLocal(
							coinsDeposited > 1 ? "general.currency.multiple" : "general.currency.single")));
		}
		player.sendMessage(new TextComponentString(I18n.translateToLocal("item.card.balance") + " "
				+ formatter.format(UniversalAccounts.getInstance().getAccountBalance(accountNumber))));
		return EnumActionResult.SUCCESS;
	}

} @SuppressWarnings("deprecation")
public class ItemFifthCoin extends ItemCoin {

	public ItemFifthCoin() {
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn)
    {
		DecimalFormat formatter = new DecimalFormat("###,###,###,###,###");
		tooltip.add(formatter.format(stack.getCount() * UniversalCoins.coinValues[4]) + " "
				+ I18n.translateToLocal("general.currency.multiple"));
	}
} public class ItemFourthCoin extends ItemCoin {

	public ItemFourthCoin() {
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		DecimalFormat formatter = new DecimalFormat("###,###,###,###,###");
		tooltip.add(formatter.format(stack.getCount() * UniversalCoins.coinValues[3]) + " "
				+ I18n.translateToLocal("general.currency.multiple"));
	}
} public class ItemLinkCard extends Item {

	public ItemLinkCard() {
		super();
		setCreativeTab(UniversalCoins.tabUniversalCoins);
		this.maxStackSize = 1;
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		if (stack.hasTagCompound()) {
			tooltip.add(I18n.translateToLocal("item.link_card.stored"));
		} else {
			tooltip.add(I18n.translateToLocal("item.link_card.blank"));
		}
	}

	@Override
	public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
			EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (worldIn.isRemote)
			return EnumActionResult.FAIL;
		RayTraceResult movingobjectposition = this.rayTrace(worldIn, player, true);

		if (movingobjectposition != null && movingobjectposition.typeOfHit == RayTraceResult.Type.BLOCK) {
			BlockPos cursorPos = movingobjectposition.getBlockPos();
			if (worldIn.getTileEntity(cursorPos) instanceof TileEntityChest) {
				// notify player we have a chest
				player.sendMessage(new TextComponentString(I18n.translateToLocal("item.link_card.message.stored")
						+ cursorPos.getX() + " " + cursorPos.getY() + " " + cursorPos.getZ()));
				player.getActiveItemStack().getTagCompound().setIntArray("storageLocation",
						new int[] { cursorPos.getX(), cursorPos.getY(), cursorPos.getZ() });
			}
			if (worldIn.getTileEntity(cursorPos) instanceof TileVendor) {
				TileVendor te = (TileVendor) worldIn.getTileEntity(cursorPos);
				if (player.getActiveItemStack().hasTagCompound()) {
					int[] storageLocation = player.getActiveItemStack().getTagCompound().getIntArray("storageLocation");
					player.sendMessage(new TextComponentString(I18n.translateToLocal("item.link_card.message.set")));
					te.setRemoteStorage(storageLocation);
					player.inventory.decrStackSize(player.inventory.currentItem, 1);
				}
			}
		}
		return EnumActionResult.SUCCESS;
	}
} public class ItemPackage extends Item {

	public ItemPackage() {
		super();
		this.maxStackSize = 1;
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		NBTTagList tagList = stack.getTagCompound().getTagList("Inventory", Constants.NBT.TAG_COMPOUND);
		for (int i = 0; i < tagList.tagCount(); i++) {
			NBTTagCompound tag = (NBTTagCompound) tagList.getCompoundTagAt(i);
			int itemCount = new ItemStack(tag).getCount();
			String itemName = new ItemStack(tag).getDisplayName();
			if (itemCount > 0) {
				tooltip.add(itemCount + " " + itemName);
			}
		}
	}

	@Override
	public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
			EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (player.getHeldItem(hand).getTagCompound() != null) {
			NBTTagList tagList = player.getHeldItem(hand).getTagCompound().getTagList("Inventory",
					Constants.NBT.TAG_COMPOUND);
			for (int i = 0; i < tagList.tagCount(); i++) {
				NBTTagCompound tag = (NBTTagCompound) tagList.getCompoundTagAt(i);
				ItemStack stack = new ItemStack(tag);
				if (!stack.isEmpty()) {
					if (player.inventory.getFirstEmptyStack() != -1) {
						player.inventory.addItemStackToInventory(stack);
					} else {
						// spawn in world
						EntityItem entityItem = new EntityItem(worldIn, pos.getX(), pos.getY(), pos.getZ(), stack);
						worldIn.spawnEntity(entityItem);
					}
				}
			}
			// destroy package
			player.setHeldItem(hand, ItemStack.EMPTY);
		}
		return EnumActionResult.SUCCESS;
	}
} public class ItemSecondCoin extends ItemCoin {

	public ItemSecondCoin() {
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		DecimalFormat formatter = new DecimalFormat("###,###,###,###,###");
		tooltip.add(formatter.format(stack.getCount() * UniversalCoins.coinValues[1]) + " "
				+ I18n.translateToLocal("general.currency.multiple"));
	}
} public class ItemThirdCoin extends ItemCoin {

	public ItemThirdCoin() {
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		DecimalFormat formatter = new DecimalFormat("###,###,###,###,###");
		tooltip.add(formatter.format(stack.getCount() * UniversalCoins.coinValues[2]) + " "
				+ I18n.translateToLocal("general.currency.multiple"));
	}
} public class ItemUCCard extends Item {

	public ItemUCCard() {
		super();
		this.maxStackSize = 1;
		setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
		if (stack.hasTagCompound()) {
			tooltip.add(stack.getTagCompound().getString("Name"));
			tooltip.add(stack.getTagCompound().getString("Account"));
		} else {
			tooltip.add(I18n.translateToLocal("item.card.warning"));
		}
	}

	@Override
	public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
			EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (!player.getHeldItem(hand).hasTagCompound()) {
			createNBT(player.getHeldItem(hand), worldIn, player);
		}
		long accountCoins = UniversalAccounts.getInstance()
				.getAccountBalance(player.getHeldItem(hand).getTagCompound().getString("Account"));
		DecimalFormat formatter = new DecimalFormat("###,###,###,###,###,###,###");
		player.sendMessage(new TextComponentString(
				I18n.translateToLocal("item.card.balance") + " " + formatter.format(accountCoins)));
		return EnumActionResult.SUCCESS;
	}

	@Override
	public void onCreated(ItemStack stack, World world, EntityPlayer entityPlayer) {
		if (!world.isRemote)
			createNBT(stack, world, entityPlayer);
	}

	protected void createNBT(ItemStack stack, World world, EntityPlayer entityPlayer) {
		String accountNumber = UniversalAccounts.getInstance()
				.getOrCreatePlayerAccount(entityPlayer.getPersistentID().toString());
		NBTTagCompound tag = new NBTTagCompound();
		tag.setTag("Name", new NBTTagString(entityPlayer.getName()));
		tag.setTag("Owner", new NBTTagString(entityPlayer.getPersistentID().toString()));
		tag.setTag("Account", new NBTTagString(accountNumber));
		stack.setTagCompound(tag);
	}
} public class ItemUCSign extends ItemSign {

	public ItemUCSign() {
		this.maxStackSize = 16;
		this.setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
			EnumFacing facing, float hitX, float hitY, float hitZ) {
		IBlockState iblockstate = worldIn.getBlockState(pos);
		boolean flag = iblockstate.getBlock().isReplaceable(worldIn, pos);

		if (facing != EnumFacing.DOWN && (iblockstate.getMaterial().isSolid() || flag)
				&& (!flag || facing == EnumFacing.UP)) {
			pos = pos.offset(facing);
			ItemStack itemstack = player.getHeldItem(hand);

			if (player.canPlayerEdit(pos, facing, itemstack) && Blocks.STANDING_SIGN.canPlaceBlockAt(worldIn, pos)) {
				if (worldIn.isRemote) {
					return EnumActionResult.SUCCESS;
				} else {
					pos = flag ? pos.down() : pos;
					if (facing == EnumFacing.UP) {
						int i = MathHelper.floor((double) ((player.rotationYaw + 180.0F) * 16.0F / 360.0F) + 0.5D) & 15;
						worldIn.setBlockState(pos, UniversalCoins.Blocks.standing_ucsign.getDefaultState()
								.withProperty(BlockUCStandingSign.ROTATION, Integer.valueOf(i)), 3);
					} else {
						worldIn.setBlockState(pos, UniversalCoins.Blocks.wall_ucsign.getDefaultState()
								.withProperty(BlockUCWallSign.FACING, facing), 3);
					}

					player.getHeldItem(hand).shrink(1);
					TileEntity tileentity = worldIn.getTileEntity(pos);

					if (tileentity instanceof TileUCSign) {
						((TileUCSign) tileentity).blockOwner = player.getName();
						player.openGui(UniversalCoins.instance, 0, worldIn, pos.getX(), pos.getY(), pos.getZ());
					}

					return EnumActionResult.SUCCESS;
				}
			} else {
				return EnumActionResult.FAIL;
			}
		} else {
			return EnumActionResult.FAIL;
		}
	}
} public class ItemVendorWrench extends Item {

	public ItemVendorWrench() {
		super();
		setFull3D();
		setMaxStackSize(1);
		setCreativeTab(UniversalCoins.tabUniversalCoins);
	}

	@Override
	public boolean doesSneakBypassUse(ItemStack stack, net.minecraft.world.IBlockAccess world, BlockPos pos,
			EntityPlayer player) {
		return true;
	}

	@Override
	public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
			EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (!worldIn.isRemote) {
			worldIn.getMinecraftServer().sendMessage(new TextComponentString("Wrench used by " + player.getDisplayName()
					+ " in World " + worldIn.provider.getDimension() + " at " + hitX + " " + hitY + " " + hitZ));
		}
		return EnumActionResult.SUCCESS;
	}
} public class ATMWithdrawalMessage implements IMessage, IMessageHandler<ATMWithdrawalMessage, IMessage> {
	private int x, y, z, withdrawalAmount;

	public ATMWithdrawalMessage() {
	}

	public ATMWithdrawalMessage(int x, int y, int z, int withdrawalAmount) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.withdrawalAmount = withdrawalAmount;
	}

	@Override
	public void toBytes(ByteBuf buf) {
		buf.writeInt(x);
		buf.writeInt(y);
		buf.writeInt(z);
		buf.writeInt(withdrawalAmount);
	}

	@Override
	public void fromBytes(ByteBuf buf) {
		this.x = buf.readInt();
		this.y = buf.readInt();
		this.z = buf.readInt();
		this.withdrawalAmount = buf.readInt();
	}

	@Override
	public IMessage onMessage(final ATMWithdrawalMessage message, final MessageContext ctx) {
		Runnable task = new Runnable() {
			@Override
			public void run() {
				processMessage(message, ctx);
			}
		};
		if (ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(task);
		} else if (ctx.side == Side.SERVER) {
			EntityPlayerMP playerEntity = ctx.getServerHandler().player;
			if (playerEntity == null) {
				FMLLog.log.warn("onMessage-server: Player is null");
				return null;
			}
			playerEntity.getServerWorld().addScheduledTask(task);
		}
		return null;
	}

	private void processMessage(ATMWithdrawalMessage message, final MessageContext ctx) {
		World world = ctx.getServerHandler().player.world;

		TileEntity tileEntity = world.getTileEntity(new BlockPos(message.x, message.y, message.z));
		if (tileEntity instanceof TileATM) {
			((TileATM) tileEntity).startCoinWithdrawal(message.withdrawalAmount);
		}
	}
} public class UCButtonMessage implements IMessage, IMessageHandler<UCButtonMessage, IMessage> {
	private int x, y, z, buttonId;
	private boolean shiftPressed;

	public UCButtonMessage() {
	}

	public UCButtonMessage(int x, int y, int z, int button, boolean shift) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.buttonId = button;
		this.shiftPressed = shift;
	}

	@Override
	public void toBytes(ByteBuf buf) {
		buf.writeInt(x);
		buf.writeInt(y);
		buf.writeInt(z);
		buf.writeInt(buttonId);
		buf.writeBoolean(shiftPressed);
	}

	@Override
	public void fromBytes(ByteBuf buf) {
		this.x = buf.readInt();
		this.y = buf.readInt();
		this.z = buf.readInt();
		this.buttonId = buf.readInt();
		this.shiftPressed = buf.readBoolean();
	}

	public IMessage onMessage(final UCButtonMessage message, final MessageContext ctx) {
		Runnable task = new Runnable() {
			@Override
			public void run() {
				processMessage(message, ctx);
			}
		};
		if (ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(task);
		} else if (ctx.side == Side.SERVER) {
			EntityPlayerMP playerEntity = ctx.getServerHandler().player;
			if (playerEntity == null) {
				FMLLog.log.warn("onMessage-server: Player is null");
				return null;
			}
			playerEntity.getServerWorld().addScheduledTask(task);
		}
		return null;
	}

	private void processMessage(UCButtonMessage message, final MessageContext ctx) {
		World world = ctx.getServerHandler().player.world;

		TileEntity tileEntity = world.getTileEntity(new BlockPos(message.x, message.y, message.z));
		if (tileEntity instanceof TileTradeStation) {
			((TileTradeStation) tileEntity).onButtonPressed(message.buttonId, message.shiftPressed);
		}
		if (tileEntity instanceof TileATM) {
			((TileATM) tileEntity).onButtonPressed(message.buttonId);
		}
		if (tileEntity instanceof TileSignal) {
			((TileSignal) tileEntity).onButtonPressed(message.buttonId, message.shiftPressed);
		}
		if (tileEntity instanceof TilePackager) {
			((TilePackager) tileEntity).onButtonPressed(message.buttonId, message.shiftPressed);
		}
		if (tileEntity instanceof TileVendor) {
			((TileVendor) tileEntity).onButtonPressed(message.buttonId, message.shiftPressed);
		}
		if (tileEntity instanceof TilePowerReceiver) {
			((TilePowerReceiver) tileEntity).onButtonPressed(message.buttonId, message.shiftPressed);
		}
		if (tileEntity instanceof TilePowerTransmitter) {
			((TilePowerTransmitter) tileEntity).onButtonPressed(message.buttonId, message.shiftPressed);
		}
	}
} public class UCPackagerServerMessage implements IMessage, IMessageHandler<UCPackagerServerMessage, IMessage> {
	private int x, y, z;
	private String packageTarget;
	private boolean tabPressed;

	public UCPackagerServerMessage() {
	}

	public UCPackagerServerMessage(int x, int y, int z, String packageTarget, boolean tabPressed) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.packageTarget = packageTarget;
		this.tabPressed = tabPressed;
	}

	@Override
	public void toBytes(ByteBuf buf) {
		buf.writeInt(x);
		buf.writeInt(y);
		buf.writeInt(z);
		ByteBufUtils.writeUTF8String(buf, packageTarget);
		buf.writeBoolean(tabPressed);
	}

	@Override
	public void fromBytes(ByteBuf buf) {
		this.x = buf.readInt();
		this.y = buf.readInt();
		this.z = buf.readInt();
		this.packageTarget = ByteBufUtils.readUTF8String(buf);
		this.tabPressed = buf.readBoolean();
	}

	@Override
	public IMessage onMessage(UCPackagerServerMessage message, MessageContext ctx) {
		World world = ctx.getServerHandler().player.world;

		TileEntity tileEntity = world.getTileEntity(new BlockPos(message.x, message.y, message.z));
		if (tileEntity instanceof TilePackager) {
			((TilePackager) tileEntity).playerLookup(message.packageTarget, message.tabPressed);
		}
		return null;
	}
} public class UCSignServerMessage implements IMessage, IMessageHandler<UCSignServerMessage, IMessage> {
	private int x, y, z;
	private ITextComponent signText0, signText1, signText2, signText3;

	public UCSignServerMessage() {
	}

	public UCSignServerMessage(int x, int y, int z, ITextComponent[] signText) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.signText0 = signText[0];
		this.signText1 = signText[1];
		this.signText2 = signText[2];
		this.signText3 = signText[3];
	}

	@Override
	public void toBytes(ByteBuf buf) {
		buf.writeInt(x);
		buf.writeInt(y);
		buf.writeInt(z);
		ByteBufUtils.writeUTF8String(buf, signText0.getFormattedText());
		ByteBufUtils.writeUTF8String(buf, signText1.getFormattedText());
		ByteBufUtils.writeUTF8String(buf, signText2.getFormattedText());
		ByteBufUtils.writeUTF8String(buf, signText3.getFormattedText());
	}

	@Override
	public void fromBytes(ByteBuf buf) {
		this.x = buf.readInt();
		this.y = buf.readInt();
		this.z = buf.readInt();
		this.signText0 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.signText1 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.signText2 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.signText3 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
	}

	@Override
	public IMessage onMessage(final UCSignServerMessage message, final MessageContext ctx) {
		Runnable task = new Runnable() {
			@Override
			public void run() {
				processMessage(message, ctx);
			}
		};
		if (ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(task);
		} else if (ctx.side == Side.SERVER) {
			EntityPlayerMP playerEntity = ctx.getServerHandler().player;
			if (playerEntity == null) {
				FMLLog.log.warn("onMessage-server: Player is null");
				return null;
			}
			playerEntity.getServerWorld().addScheduledTask(task);
		}
		return null;
	}

	private void processMessage(UCSignServerMessage message, final MessageContext ctx) {
		World world = ctx.getServerHandler().player.world;

		TileEntity tileEntity = world.getTileEntity(new BlockPos(message.x, message.y, message.z));
		if (tileEntity != null && tileEntity instanceof TileUCSign) {
			TileUCSign tentity = (TileUCSign) tileEntity;
			tentity.signText[0] = message.signText0;
			tentity.signText[1] = message.signText1;
			tentity.signText[2] = message.signText2;
			tentity.signText[3] = message.signText3;
			tentity.updateSign();
			tentity.markDirty();
		}
	}
} public class UCTileSignMessage implements IMessage, IMessageHandler<UCTileSignMessage, IMessage> {
	private int xCoord;
	private int yCoord;
	private int zCoord;
	private ITextComponent signText0, signText1, signText2, signText3;
	private String blockOwner;

	public UCTileSignMessage() {
	}

	public UCTileSignMessage(int x, int y, int z, ITextComponent[] signText, String blockOwner) {
		this.xCoord = x;
		this.yCoord = y;
		this.zCoord = z;
		this.signText0 = signText[0];
		this.signText1 = signText[1];
		this.signText2 = signText[2];
		this.signText3 = signText[3];
		this.blockOwner = blockOwner;
	}

	@Override
	public void fromBytes(ByteBuf buf) {
		this.xCoord = buf.readInt();
		this.yCoord = buf.readShort();
		this.zCoord = buf.readInt();
		this.signText0 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.signText1 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.signText2 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.signText3 = new TextComponentString(ByteBufUtils.readUTF8String(buf));
		this.blockOwner = ByteBufUtils.readUTF8String(buf);
	}

	@Override
	public void toBytes(ByteBuf buf) {
		buf.writeInt(this.xCoord);
		buf.writeShort(this.yCoord);
		buf.writeInt(this.zCoord);
		ByteBufUtils.writeUTF8String(buf, signText0.getUnformattedText());
		ByteBufUtils.writeUTF8String(buf, signText1.getUnformattedText());
		ByteBufUtils.writeUTF8String(buf, signText2.getUnformattedText());
		ByteBufUtils.writeUTF8String(buf, signText3.getUnformattedText());
		ByteBufUtils.writeUTF8String(buf, this.blockOwner);
	}

	@Override
	public IMessage onMessage(final UCTileSignMessage message, final MessageContext ctx) {
		Runnable task = new Runnable() {
			@Override
			public void run() {
				processMessage(message, ctx);
			}
		};
		if (ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(task);
		} else if (ctx.side == Side.SERVER) {
			EntityPlayerMP playerEntity = ctx.getServerHandler().player;
			if (playerEntity == null) {
				FMLLog.log.warn("onMessage-server: Player is null");
				return null;
			}
			playerEntity.getServerWorld().addScheduledTask(task);
		}
		return null;
	}

	private void processMessage(UCTileSignMessage message, final MessageContext ctx) {
		TileEntity tileEntity = FMLClientHandler.instance().getClient().world
				.getTileEntity(new BlockPos(message.xCoord, message.yCoord, message.zCoord));

		if (tileEntity != null && tileEntity instanceof TileUCSign) {
			TileUCSign tentity = (TileUCSign) tileEntity;
			tentity.signText[0] = message.signText0;
			tentity.signText[1] = message.signText1;
			tentity.signText[2] = message.signText2;
			tentity.signText[3] = message.signText3;
			tentity.blockOwner = message.blockOwner;
		}
	}
} public class UCVendorServerMessage implements IMessage, IMessageHandler<UCVendorServerMessage, IMessage> {
	private int x, y, z, itemPrice;
	private String blockOwner;
	private boolean infinite;

	public UCVendorServerMessage() {
	}

	public UCVendorServerMessage(int x, int y, int z, int price, String blockOwner, boolean infinite) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.itemPrice = price;
		this.blockOwner = blockOwner;
		this.infinite = infinite;
	}

	@Override
	public void toBytes(ByteBuf buf) {
		buf.writeInt(x);
		buf.writeInt(y);
		buf.writeInt(z);
		buf.writeInt(itemPrice);
		ByteBufUtils.writeUTF8String(buf, blockOwner);
		buf.writeBoolean(infinite);
	}

	@Override
	public void fromBytes(ByteBuf buf) {
		this.x = buf.readInt();
		this.y = buf.readInt();
		this.z = buf.readInt();
		this.itemPrice = buf.readInt();
		this.blockOwner = ByteBufUtils.readUTF8String(buf);
		this.infinite = buf.readBoolean();
	}

	@Override
	public IMessage onMessage(final UCVendorServerMessage message, final MessageContext ctx) {
		Runnable task = new Runnable() {
			@Override
			public void run() {
				processMessage(message, ctx);
			}
		};
		if (ctx.side == Side.CLIENT) {
			Minecraft.getMinecraft().addScheduledTask(task);
		} else if (ctx.side == Side.SERVER) {
			EntityPlayerMP playerEntity = ctx.getServerHandler().player;
			if (playerEntity == null) {
				return null;
			}
			playerEntity.getServerWorld().addScheduledTask(task);
		}
		return null;
	}

	private void processMessage(UCVendorServerMessage message, final MessageContext ctx) {
		World world = ctx.getServerHandler().player.world;

		TileEntity tileEntity = world.getTileEntity(new BlockPos(message.x, message.y, message.z));
		if (tileEntity instanceof TileVendor) {
			TileVendor tEntity = (TileVendor) tileEntity;
			tEntity.itemPrice = message.itemPrice;
			tEntity.blockOwner = message.blockOwner;
			tEntity.infiniteMode = message.infinite;
		}
		if (tileEntity instanceof TileVendorFrame) {
			((TileVendorFrame) tileEntity).updateSigns();
		}
		if (tileEntity instanceof TileVendorBlock) {
			((TileVendorBlock) tileEntity).updateSigns();
		}
	}
} public class SignalRenderer extends TileEntitySpecialRenderer<TileEntity> {

	public SignalRenderer() {
	}

	public void render(TileEntity tileentity, double x, double y, double z, float partialTicks, int destroyStage,
			float alpha) {
		TileSignal te = (TileSignal) tileentity;

		// adjust block rotation based on block meta
		int meta = tileentity.getBlockMetadata();
		if (meta == -1) { // fix for inventory crash on get block meta
			try {
				meta = tileentity.getBlockMetadata();
			} catch (Throwable ex2) {
				// do nothing
			}
		}

		GL11.glPushMatrix();
		float correction = 0.0F;
		if (meta == 2) {
			correction = 180.0F;
		}
		if (meta == 4) {
			correction = 90.0F;
		}
		if (meta == 5) {
			correction = -90.0F;
		}
		GlStateManager.translate((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F);
		GlStateManager.rotate(-correction, 0.0F, 1.0F, 0.0F);
		GlStateManager.translate(-0.5F, -0.5F, -0.5F);

		// draw text on front face
		FontRenderer fontrenderer = this.getFontRenderer();
		byte b0 = 0;

		if (fontrenderer != null) {
			float f1 = 0.6666667F;
			float f3 = 0.016666668F * f1;
			GL11.glTranslatef(0.5F, 1F, 1.0F + f3);
			GL11.glScalef(0.01F, -f3, f3);
			GL11.glDepthMask(false);
			if (te.secondsLeft > 0) {
				int time = te.secondsLeft;
				String s = time + " " + (time > 1 ? I18n.translateToLocal("signal.face.label.seconds")
						: I18n.translateToLocal("signal.face.label.second"));
				fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, 16, b0);
			} else {
				int duration = te.duration;
				int coins = te.fee;
				String s = coins + " " + (coins > 1 ? I18n.translateToLocal("signal.face.label.coins")
						: I18n.translateToLocal("signal.face.label.coin"));
				fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, 6, b0);
				String s2 = duration + " " + (duration > 1 ? I18n.translateToLocal("signal.face.label.seconds")
						: I18n.translateToLocal("signal.face.label.second"));
				fontrenderer.drawString(s2, -fontrenderer.getStringWidth(s2) / 2, 16, b0);
			}
			GL11.glDepthMask(true);
			GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		}

		GL11.glPopMatrix();
	}
} @SideOnly(Side.CLIENT)
public class UCSignRenderer extends TileEntitySpecialRenderer<TileEntitySign> {
	private int counter = 0;
	private final ModelSign model = new ModelSign();

	public void renderTileEntityAt(TileUCSign tileEntity, double posX, double posY, double posZ, float partialTicks,
			int destroyStage) {
		TileUCSign te = null;
		float f3;
		if (tileEntity instanceof TileUCSign) {
			te = (TileUCSign) tileEntity;
		} else {
			return;
		}
		ResourceLocation blockTexture = new ResourceLocation("universalcoins:textures/entity/uc_sign.png");
		new ModelSign();

		Block block = te.getBlockType();
		GlStateManager.pushMatrix();
		float f = 0.6666667F;

		if (block == UniversalCoins.Blocks.standing_ucsign) {
			GlStateManager.translate((float) posX + 0.5F, (float) posY + 0.75F * f, (float) posZ + 0.5F);
			float f1 = (float) (te.getBlockMetadata() * 360) / 16.0F;
			GlStateManager.rotate(-f1, 0.0F, 1.0F, 0.0F);
			this.model.signStick.showModel = true;
		} else {
			int k = te.getBlockMetadata();
			float f2 = 0.0F;

			if (k == 2) {
				f2 = 180.0F;
			}

			if (k == 4) {
				f2 = 90.0F;
			}

			if (k == 5) {
				f2 = -90.0F;
			}

			GlStateManager.translate((float) posX + 0.5F, (float) posY + 0.75F * f, (float) posZ + 0.5F);
			GlStateManager.rotate(-f2, 0.0F, 1.0F, 0.0F);
			GlStateManager.translate(0.0F, -0.3125F, -0.4375F);
			this.model.signStick.showModel = false;
		}

		if (destroyStage >= 0) {
			this.bindTexture(DESTROY_STAGES[destroyStage]);
			GlStateManager.matrixMode(5890);
			GlStateManager.pushMatrix();
			GlStateManager.scale(4.0F, 2.0F, 1.0F);
			GlStateManager.translate(0.0625F, 0.0625F, 0.0625F);
			GlStateManager.matrixMode(5888);
		} else {
			this.bindTexture(blockTexture);
		}

		// GlStateManager.enableRescaleNormal();
		GlStateManager.pushMatrix();
		GlStateManager.scale(f, -f, -f);
		this.model.renderSign();
		GlStateManager.popMatrix();
		FontRenderer fontrenderer = this.getFontRenderer();
		f3 = 0.016666668F * f;
		GlStateManager.translate(0.0F, 0.5F * f, 0.07F * f);
		GlStateManager.scale(f3, -f3, f3);
		GL11.glNormal3f(0.0F, 0.0F, -1.0F * f3);
		GlStateManager.depthMask(false);

		int[] colors = { 0x000000, 0x0000AA, 0x00AA00, 0x00AAAA, 0xAA0000, 0xAA00AA, 0xFFAA00, 0xAAAAAA, 0x555555,
				0x5555FF, 0x55FF55, 0x55FFFF, 0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF };

		for (int i = 0; i < te.signText.length; ++i) {
			String s = te.signText[i].getUnformattedText();
			int colorCode = 0;
			if (s.startsWith("§r"))
				s = s.substring(2);
			if (s.startsWith("&") && s.length() > 1 && String.valueOf(s.charAt(1)).matches("[0-9a-fA-F]+")) {
				colorCode = Integer.parseInt(s.substring(1, 2), 16);
				s = s.substring(2);
			}

			if (i == te.lineBeingEdited) {
				s = "> " + s + " <";
				fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, i * 10 - te.signText.length * 5,
						colors[colorCode]);
			} else {
				if (s.length() <= 16) {
					fontrenderer.drawString(s, -fontrenderer.getStringWidth(s) / 2, i * 10 - te.signText.length * 5,
							colors[colorCode]);
				} else {
					// display a subset of string while scrolling through entire
					// string
					String subset = "";
					if (counter / 30 < s.length() - 8) {
						subset = s.substring(Math.min(counter / 30, s.length() - 15),
								Math.min(counter / 30 + 15, s.length()));
					} else {
						subset = s.substring(0, 15);
					}
					fontrenderer.drawString(subset, -fontrenderer.getStringWidth(subset) / 2,
							i * 10 - te.signText.length * 5, colors[colorCode]);
					counter++;
					if (counter / 30 > s.length() + 8)
						counter = 0;
				}
			}
		}
		GlStateManager.depthMask(true);
		GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
		GlStateManager.popMatrix();

		if (destroyStage >= 0) {
			GlStateManager.matrixMode(5890);
			GlStateManager.popMatrix();
			GlStateManager.matrixMode(5888);
		}
	}

	@Override
	public void render(TileEntitySign te, double x, double y, double z, float partialTicks, int destroyStage,
			float alpha) {
		this.renderTileEntityAt((TileUCSign) te, x, y, z, partialTicks, destroyStage);

	}
} @SuppressWarnings("rawtypes")
public class VendorBlockRenderer extends TileEntitySpecialRenderer {

	public VendorBlockRenderer() {
	}

	@Override
	public void render(TileEntity te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
		TileVendor tVendor = (TileVendor) te;

		if (tVendor == null || tVendor.getBlockType() == null) {
			return;
		}

		ItemStack itemstack = tVendor.getSellItem();

		if (itemstack.isEmpty()) {
			return;
		}
		EntityItem entity = new EntityItem(null, x, y, z, itemstack);

		entity.hoverStart = 0;

		GlStateManager.pushMatrix();
		GlStateManager.translate((float) x + 0.5F, (float) y + 0.15F, (float) z + 0.5F);

		try {
			// render trade item
			Minecraft.getMinecraft().getRenderManager().renderEntity(entity, 0.0D, 0.0D, 0.0D, 0.0F,
					Minecraft.getMinecraft().player.ticksExisted, false);
		} catch (Throwable e) {
		}
		GlStateManager.popMatrix();
	}
} public class VendorFrameRenderer extends TileEntitySpecialRenderer<TileEntity> {

	public VendorFrameRenderer() {
	}

	@Override
	public void render(TileEntity te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
		// get trade item or block
		ItemStack itemstack = ((TileVendorFrame) te).getSellItem();

		// exit if nothing is set
		if (itemstack.isEmpty()) {
			return;
		}

		GlStateManager.pushMatrix();
		GlStateManager.disableLighting();

		// adjust block rotation based on block meta
		int meta = 0;
		try {
			meta = te.getBlockMetadata();
		} catch (Throwable ex2) {
			// do nothing
		}
		float correction = 0.0F;
		if (meta == 2) {
			correction = 0.0F;
		}
		if (meta == 3) {
			correction = 180.0F;
		}
		if (meta == 4) {
			correction = 90.0F;
		}
		if (meta == 5) {
			correction = -90.0F;
		}
		GlStateManager.translate((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F);
		GlStateManager.rotate(correction, 0F, 1F, 0F);
		GlStateManager.translate(-0.0F, -0.0F, -0.45F);
		GlStateManager.scale(0.5F, 0.5F, 0.5F);
		GlStateManager.pushAttrib();
		RenderHelper.enableStandardItemLighting();
		Minecraft.getMinecraft().getRenderItem().renderItem(itemstack, ItemCameraTransforms.TransformType.FIXED);
		RenderHelper.disableStandardItemLighting();
		GlStateManager.popAttrib();
		GlStateManager.enableLighting();
		GlStateManager.popMatrix();
	}
} public class TileATM extends TileProtected implements IInventory {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(2, ItemStack.EMPTY);
	public static final int itemCoinSlot = 0;
	public static final int itemCardSlot = 1;
	public String blockOwner = "";
	public String playerName = "";
	public String playerUID = "";
	public boolean inUse = false;
	public boolean depositCoins = false;
	public boolean withdrawCoins = false;
	public boolean accountError = false;
	public int coinWithdrawalAmount = 0;
	public String cardOwner = "";
	public String accountNumber = "none";
	public long accountBalance = 0;

	public void inUseCleanup() {
		if (world.isRemote)
			return;
		inUse = false;
		withdrawCoins = false;
		depositCoins = false;
		accountNumber = "none";
		accountBalance = 0;
		updateTE();
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (size < stack.getCount()) {
			stack = stack.splitStack(size);
		} else {
			setInventorySlotContents(slot, ItemStack.EMPTY);
		}
		fillCoinSlot();
		return stack;
	}

	// @Override
	public ItemStack getStackInSlotOnClosing(int slot) {
		ItemStack itemstack = this.inventory.get(slot);
		inventory.remove(slot);
		return itemstack;
	}

	@Override
	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
		if (slot == itemCoinSlot) {
			int coinValue = CoinUtils.getCoinValue(stack);
			if (depositCoins && coinValue > 0) {
				long depositAmount = Math.min(stack.getCount(), (Long.MAX_VALUE - accountBalance) / coinValue);
				if (!world.isRemote) {
					UniversalAccounts.getInstance().creditAccount(accountNumber, depositAmount * coinValue, false);
					accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
				}
				ItemStack newStack = inventory.get(slot);
				newStack.shrink((int) depositAmount);
				inventory.set(slot, newStack);
				if (inventory.get(slot).getCount() == 0) {
					inventory.set(slot, ItemStack.EMPTY);
				}
			}
		}
		if (slot == itemCardSlot && !world.isRemote)

		{
			if (!inventory.get(itemCardSlot).hasTagCompound()) {
				return;
			}
			accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			cardOwner = inventory.get(itemCardSlot).getTagCompound().getString("Owner");
			accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
		}
	}

	@Override
	public String getName() {
		return UniversalCoins.Blocks.atm.getLocalizedName();
	}

	@Override
	public boolean hasCustomName() {
		return false;
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	public void sendServerUpdatePacket(int withdrawalAmount) {
		UniversalCoins.snw.sendToServer(new ATMWithdrawalMessage(pos.getX(), pos.getY(), pos.getZ(), withdrawalAmount));
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);

		NBTTagList tagList = tagCompound.getTagList("Inventory", Constants.NBT.TAG_COMPOUND);
		for (int i = 0; i < tagList.tagCount(); i++) {
			NBTTagCompound tag = (NBTTagCompound) tagList.getCompoundTagAt(i);
			byte slot = tag.getByte("Slot");
			if (slot >= 0 && slot < inventory.size()) {
				inventory.get(slot).deserializeNBT(tag);
			}
		}
		try {
			blockOwner = tagCompound.getString("BlockOwner");
		} catch (Throwable ex2) {
			blockOwner = null;
		}
		try {
			inUse = tagCompound.getBoolean("InUse");
		} catch (Throwable ex2) {
			inUse = false;
		}
		try {
			depositCoins = tagCompound.getBoolean("DepositCoins");
		} catch (Throwable ex2) {
			depositCoins = false;
		}
		try {
			withdrawCoins = tagCompound.getBoolean("WithdrawCoins");
		} catch (Throwable ex2) {
			withdrawCoins = false;
		}
		try {
			coinWithdrawalAmount = tagCompound.getInteger("CoinWithdrawalAmount");
		} catch (Throwable ex2) {
			coinWithdrawalAmount = 0;
		}
		try {
			cardOwner = tagCompound.getString("CardOwner");
		} catch (Throwable ex2) {
			cardOwner = "";
		}
		try {
			accountNumber = tagCompound.getString("accountNumber");
		} catch (Throwable ex2) {
			accountNumber = "none";
		}
		try {
			accountBalance = tagCompound.getLong("accountBalance");
		} catch (Throwable ex2) {
			accountBalance = 0;
		}
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		NBTTagList itemList = new NBTTagList();
		for (int i = 0; i < inventory.size(); i++) {
			ItemStack stack = inventory.get(i);
			if (stack != null) {
				NBTTagCompound tag = new NBTTagCompound();
				tag.setByte("Slot", (byte) i);
				stack.writeToNBT(tag);
				itemList.appendTag(tag);
			}
		}
		tagCompound.setTag("Inventory", itemList);
		tagCompound.setString("BlockOwner", blockOwner);
		tagCompound.setBoolean("InUse", inUse);
		tagCompound.setBoolean("DepositCoins", depositCoins);
		tagCompound.setBoolean("WithdrawCoins", withdrawCoins);
		tagCompound.setInteger("CoinWithdrawalAmount", coinWithdrawalAmount);
		tagCompound.setString("CardOwner", cardOwner);
		tagCompound.setString("accountNumber", accountNumber);
		tagCompound.setLong("accountBalance", accountBalance);

		markDirty();
		return tagCompound;
	}

	@Override
	public boolean isItemValidForSlot(int var1, ItemStack var2) {
		return true;
	}

	public void onButtonPressed(int functionId) {
		if (world.isRemote)
			return;
		accountError = false; // reset error state
		// handle function IDs sent from CardStationGUI
		// function1 - new card
		// function2 - transfer account
		// function3 - deposit
		// function4 - withdraw
		// function5 - get account info
		// function6 - destroy invalid card
		if (functionId == 1) {
			accountNumber = UniversalAccounts.getInstance().getOrCreatePlayerAccount(playerUID);
			if (UniversalAccounts.getInstance().getAccountBalance(accountNumber) > 1000000) {
				inventory.set(itemCardSlot, new ItemStack(UniversalCoins.Items.ender_card, 1));
			} else {
				inventory.set(itemCardSlot, new ItemStack(UniversalCoins.Items.uc_card, 1));
			}
			inventory.get(itemCardSlot).setTagCompound(new NBTTagCompound());
			inventory.get(itemCardSlot).getTagCompound().setString("Name", playerName);
			inventory.get(itemCardSlot).getTagCompound().setString("Owner", playerUID);
			inventory.get(itemCardSlot).getTagCompound().setString("Account", accountNumber);
			accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
			cardOwner = playerUID;
		}
		if (functionId == 2) {
			if (!(UniversalAccounts.getInstance().getPlayerAccount(playerUID).matches(""))) {
				UniversalAccounts.getInstance().transferPlayerAccount(playerUID);
				inventory.set(itemCardSlot, new ItemStack(UniversalCoins.Items.uc_card, 1));
				inventory.get(itemCardSlot).setTagCompound(new NBTTagCompound());
				inventory.get(itemCardSlot).getTagCompound().setString("Name", playerName);
				inventory.get(itemCardSlot).getTagCompound().setString("Owner", playerUID);
				inventory.get(itemCardSlot).getTagCompound().setString("Account",
						UniversalAccounts.getInstance().getPlayerAccount(playerUID));
				accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
				cardOwner = playerUID;
			}
		}
		if (functionId == 3) {
			// set to true if player presses deposit button, reset on any other
			// button press
			depositCoins = true;
			withdrawCoins = false;
			// set account number if not already set and we have a card present
			if (accountNumber.matches("none") && inventory.get(itemCardSlot) != null) {
				accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			}
		} else {
			depositCoins = false;
		}
		if (functionId == 4) {
			withdrawCoins = true;
			depositCoins = false;
			fillCoinSlot();
		} else
			withdrawCoins = false;
		if (functionId == 5) {
			String storedAccount = UniversalAccounts.getInstance().getPlayerAccount(playerUID);
			if (!storedAccount.matches("")) {
				accountNumber = storedAccount;
				cardOwner = playerUID; // needed for new card auth
				accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
			}
		}
		if (functionId == 6) {
			inventory.set(itemCardSlot, ItemStack.EMPTY);
			inUseCleanup();
		}
	}

	public void startCoinWithdrawal(int amount) {
		if (UniversalAccounts.getInstance().debitAccount(accountNumber, amount, false)) {
			coinWithdrawalAmount = amount;
			accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
		}
	}

	public void fillCoinSlot() {
		if (inventory.get(itemCoinSlot) == ItemStack.EMPTY && coinWithdrawalAmount > 0) {
			if (coinWithdrawalAmount >= UniversalCoins.coinValues[4]) {
				inventory.set(itemCoinSlot, new ItemStack(UniversalCoins.Items.obsidian_coin));
				inventory.get(itemCoinSlot)
						.setCount((int) Math.min(coinWithdrawalAmount / UniversalCoins.coinValues[4], 64));
				coinWithdrawalAmount -= inventory.get(itemCoinSlot).getCount() * UniversalCoins.coinValues[4];
			} else if (coinWithdrawalAmount >= UniversalCoins.coinValues[3]) {
				inventory.set(itemCoinSlot, new ItemStack(UniversalCoins.Items.diamond_coin));
				inventory.get(itemCoinSlot)
						.setCount((int) Math.min(coinWithdrawalAmount / UniversalCoins.coinValues[3], 64));
				coinWithdrawalAmount -= inventory.get(itemCoinSlot).getCount() * UniversalCoins.coinValues[3];
			} else if (coinWithdrawalAmount >= UniversalCoins.coinValues[2]) {
				inventory.set(itemCoinSlot, new ItemStack(UniversalCoins.Items.emerald_coin));
				inventory.get(itemCoinSlot)
						.setCount((int) Math.min(coinWithdrawalAmount / UniversalCoins.coinValues[2], 64));
				coinWithdrawalAmount -= inventory.get(itemCoinSlot).getCount() * UniversalCoins.coinValues[2];
			} else if (coinWithdrawalAmount >= UniversalCoins.coinValues[1]) {
				inventory.set(itemCoinSlot, new ItemStack(UniversalCoins.Items.gold_coin));
				inventory.get(itemCoinSlot)
						.setCount((int) Math.min(coinWithdrawalAmount / UniversalCoins.coinValues[1], 64));
				coinWithdrawalAmount -= inventory.get(itemCoinSlot).getCount() * UniversalCoins.coinValues[1];
			} else if (coinWithdrawalAmount >= UniversalCoins.coinValues[0]) {
				inventory.set(itemCoinSlot, new ItemStack(UniversalCoins.Items.iron_coin));
				inventory.get(itemCoinSlot)
						.setCount((int) Math.min(coinWithdrawalAmount / UniversalCoins.coinValues[0], 64));
				coinWithdrawalAmount -= inventory.get(itemCoinSlot).getCount() * UniversalCoins.coinValues[0];
			}
		}
		if (coinWithdrawalAmount <= 0) {
			withdrawCoins = false;
			coinWithdrawalAmount = 0;
		}
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.atm.getLocalizedName());
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {

	}

	@Override
	public void closeInventory(EntityPlayer player) {

	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {
	}

	@Override
	public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) {
		return false;
	}

	@Override
	public boolean isEmpty() {
		return false;
	}

	public boolean isUsableByPlayer(EntityPlayer player) {
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} @SuppressWarnings("deprecation")
public class TilePackager extends TileProtected implements IInventory {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack> withSize(12, ItemStack.EMPTY);
	public static final int[] itemPackageSlot = { 0, 1, 2, 3, 4, 5, 6, 7 };
	public static final int itemCardSlot = 8;
	public static final int itemCoinSlot = 9;
	public static final int itemOutputSlot = 10;
	public static final int itemPackageInputSlot = 11;
	public long coinSum = 0;
	public boolean cardAvailable = false;
	public String customName = "";
	public String playerName = "";
	public String packageTarget = "";
	public boolean inUse = false;
	public int packageSize = 0;
	public int[] packageCost = { UniversalCoins.smallPackagePrice, UniversalCoins.medPackagePrice,
			UniversalCoins.largePackagePrice };

	public TilePackager() {
		super();
	}

	public void onButtonPressed(int buttonId, boolean shiftPressed) {
		checkCard();
		if (buttonId == 0) {
			if (shiftPressed) {
				sendPackage(packageTarget);
				return;
			}
			if (coinSum < packageCost[packageSize] && !cardAvailable) {
				return;
			}
			if (getStackInSlot(itemOutputSlot).isEmpty()) {

				NBTTagList itemList = new NBTTagList();
				NBTTagCompound tagCompound = new NBTTagCompound();
				for (int i = 0; i < itemPackageSlot.length; i++) {
					ItemStack invStack = getStackInSlot(i);
					if (invStack != null && invStack.getItem() != UniversalCoins.Items.uc_package) {
						NBTTagCompound tag = new NBTTagCompound();
						tag.setByte("Slot", (byte) i);
						invStack.writeToNBT(tag);
						itemList.appendTag(tag);
						inventory.set(i, ItemStack.EMPTY);
					}
				}
				if (itemList.tagCount() > 0) {
					inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.uc_package));
					tagCompound.setTag("Inventory", itemList);
					getStackInSlot(itemOutputSlot).setTagCompound(tagCompound);
					if (cardAvailable) {
						String account = getStackInSlot(itemCardSlot).getTagCompound().getString("Account");
						UniversalAccounts.getInstance().debitAccount(account, packageCost[packageSize], false);
					} else {
						coinSum -= packageCost[packageSize];

					}
				}
			}
		}
		if (buttonId == 1) {
			fillOutputSlot();
		}
		if (buttonId == 2) {
			packageSize = 0;
			for (int i = 0; i < 4; i++) {
				if (getStackInSlot(i) != null) {
					if (world.getPlayerEntityByName(playerName).inventory.getFirstEmptyStack() != -1) {
						world.getPlayerEntityByName(playerName).inventory.addItemStackToInventory(getStackInSlot(i));
					} else {
						// spawn in world
						EntityItem entityItem = new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(),
								getStackInSlot(i));
						world.spawnEntity(entityItem);
					}
					inventory.set(i, ItemStack.EMPTY);
				}
			}
		}
		if (buttonId == 3) {
			packageSize = 1;
			for (int i = 0; i < 2; i++) {
				if (getStackInSlot(i) != null) {
					if (world.getPlayerEntityByName(playerName).inventory.getFirstEmptyStack() != -1) {
						world.getPlayerEntityByName(playerName).inventory.addItemStackToInventory(getStackInSlot(i));
					} else {
						// spawn in world
						EntityItem entityItem = new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(),
								getStackInSlot(i));
						world.spawnEntity(entityItem);
					}
					inventory.set(i, ItemStack.EMPTY);
				}
			}
		}
		if (buttonId == 4) {
			packageSize = 2;
		}
	}

	public void inUseCleanup() {
		if (world.isRemote)
			return;
		inUse = false;
	}

	@Override
	public String getName() {
		return this.hasCustomName() ? this.customName : UniversalCoins.Blocks.packager.getLocalizedName();
	}

	public void setName(String name) {
		customName = name;
	}

	public boolean isNameLocalized() {
		return false;
	}

	@Override
	public boolean hasCustomName() {
		return this.customName != null && this.customName.length() > 0;
	}

	public void checkCard() {
		cardAvailable = false;
		if (!getStackInSlot(itemCardSlot).isEmpty() && getStackInSlot(itemCardSlot).hasTagCompound()
				&& !world.isRemote) {
			String account = getStackInSlot(itemCardSlot).getTagCompound().getString("Account");
			long accountBalance = UniversalAccounts.getInstance().getAccountBalance(account);
			if (accountBalance > packageCost[packageSize]) {
				cardAvailable = true;
			}
		}
	}

	public void sendServerUpdateMessage(String packageTarget, boolean shiftPressed) {
		UniversalCoins.snw.sendToServer(
				new UCPackagerServerMessage(pos.getX(), pos.getY(), pos.getZ(), packageTarget, shiftPressed));
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setLong("coinSum", coinSum);
		tagCompound.setBoolean("cardAvailable", cardAvailable);
		tagCompound.setString("customName", customName);
		tagCompound.setBoolean("inUse", inUse);
		tagCompound.setInteger("packageSize", packageSize);
		tagCompound.setString("packageTarget", packageTarget);
		tagCompound.setInteger("smallPrice", packageCost[0]);
		tagCompound.setInteger("medPrice", packageCost[1]);
		tagCompound.setInteger("largePrice", packageCost[2]);

		return tagCompound;
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack> withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			coinSum = tagCompound.getLong("coinSum");
		} catch (Throwable ex2) {
			coinSum = 0;
		}
		try {
			cardAvailable = tagCompound.getBoolean("cardAvailable");
		} catch (Throwable ex2) {
			cardAvailable = false;
		}
		try {
			customName = tagCompound.getString("customName");
		} catch (Throwable ex2) {
			customName = "";
		}
		try {
			inUse = tagCompound.getBoolean("inUse");
		} catch (Throwable ex2) {
			inUse = false;
		}
		try {
			packageSize = tagCompound.getInteger("packageSize");
		} catch (Throwable ex2) {
			packageSize = 0;
		}
		try {
			packageTarget = tagCompound.getString("packageTarget");
		} catch (Throwable ex2) {
			packageTarget = "";
		}
		try {
			packageCost[0] = tagCompound.getInteger("smallPrice");
		} catch (Throwable ex2) {
			packageCost[0] = UniversalCoins.smallPackagePrice;
		}
		try {
			packageCost[1] = tagCompound.getInteger("medPrice");
		} catch (Throwable ex2) {
			packageCost[1] = UniversalCoins.medPackagePrice;
		}
		try {
			packageCost[2] = tagCompound.getInteger("largePrice");
		} catch (Throwable ex2) {
			packageCost[2] = UniversalCoins.largePackagePrice;
		}
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (stack != ItemStack.EMPTY) {
			if (stack.getCount() <= size) {
				inventory.set(slot, ItemStack.EMPTY);
			} else {
				stack = stack.splitStack(size);
				if (stack.getCount() == 0) {
					inventory.set(slot, ItemStack.EMPTY);
				}
			}
			if (slot == itemCardSlot) {
				checkCard();
			}
		}
		return stack;
	}

	private void fillOutputSlot() {
		if (inventory.get(itemOutputSlot).isEmpty()) {
			if (coinSum >= UniversalCoins.coinValues[4]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.obsidian_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[4], 64));
				coinSum -= UniversalCoins.coinValues[4] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[3]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.diamond_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[3], 64));
				coinSum -= UniversalCoins.coinValues[3] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[2]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.emerald_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[2], 64));
				coinSum -= UniversalCoins.coinValues[2] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[1]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.gold_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[1], 64));
				coinSum -= UniversalCoins.coinValues[1] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[0]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.iron_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[0], 64));
				coinSum -= UniversalCoins.coinValues[0] * getStackInSlot(itemOutputSlot).getCount();
			}
		}
	}

	// @Override
	public ItemStack getStackInSlotOnClosing(int i) {
		return getStackInSlot(i);
	}

	@Override
	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
		if (slot == itemCoinSlot) {
			int coinValue = CoinUtils.getCoinValue(stack);
			if (coinValue > 0) {
				int depositAmount = (int) Math.min(stack.getCount(), (Long.MAX_VALUE - coinSum) / coinValue);
				getStackInSlot(slot).shrink(depositAmount);
				coinSum += depositAmount * coinValue;
			}
		}
		if (getStackInSlot(slot).getCount() == 0) {
			inventory.set(slot, ItemStack.EMPTY);
		}
		if (slot == itemCardSlot && getStackInSlot(itemCardSlot).getItem() == UniversalCoins.Items.ender_card) {
			if (!world.isRemote && stack.hasTagCompound()) {
				String accountNumber = stack.getTagCompound().getString("Account");
				UniversalAccounts.getInstance().creditAccount(accountNumber, coinSum, false);
				coinSum = 0;
			}
		}
		if (slot == itemCardSlot && !world.isRemote) {
			checkCard();
		}
	}

	public void sendPackage(String packageTarget) {
		if (world.isRemote)
			return;
		EntityPlayer player = world.getPlayerEntityByName(packageTarget);
		if (player != null) {
			if (player.inventory.getFirstEmptyStack() != -1) {
				player.inventory.addItemStackToInventory(getStackInSlot(itemPackageInputSlot));
			} else {
				Random rand = new Random();
				float rx = rand.nextFloat() * 0.8F + 0.1F;
				float ry = rand.nextFloat() * 0.8F + 0.1F;
				float rz = rand.nextFloat() * 0.8F + 0.1F;
				EntityItem entityItem = new EntityItem(world, player.posX + rx, player.posY + ry, player.posZ + rz,
						getStackInSlot(itemPackageInputSlot));
				world.spawnEntity(entityItem);
			}
			player.sendMessage(
					new TextComponentString("§a" + playerName + I18n.translateToLocal("packager.message.sent")));
			inventory.set(itemPackageInputSlot, ItemStack.EMPTY);
		}
	}

	public void playerLookup(String playerName, boolean tabPressed) {
		if (tabPressed) {
			List<String> players = new ArrayList<String>();
			for (EntityPlayer p : (List<EntityPlayer>) world.playerEntities) {
				players.add(p.getDisplayName().getUnformattedText());
			}
			String test[] = { playerName };
			List<String> match = CommandBase.getListOfStringsMatchingLastWord(test, players);
			if (match.size() > 0) {
				packageTarget = match.get(0).toString();
			}
		} else {
			packageTarget = playerName;
		}
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public boolean isItemValidForSlot(int var1, ItemStack var2) {
		return false;
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.packager.getLocalizedName());
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {

	}

	@Override
	public void closeInventory(EntityPlayer player) {

	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {

	}

	@Override
	public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) {
		return false;
	}

	@Override
	public boolean isEmpty() {
		return false;
	}

	public boolean isUsableByPlayer(EntityPlayer player) {
		FMLLog.log.info("isUsableByPlayer: " + player);
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} public class TilePowerReceiver extends TileProtected implements ITickable, IInventory, IEnergyStorage {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(3, ItemStack.EMPTY);
	public static final int itemCardSlot = 0;
	public static final int itemCoinSlot = 1;
	public static final int itemOutputSlot = 2;
	public long coinSum = 0;
	public int feLevel = 0;
	public int feOutput = 0;
	public long wfeLevel = 0;
	public String blockOwner = "nobody";
	public EnumFacing orientation = null;
	public boolean publicAccess;

	@CapabilityInject(IEnergyStorage.class)
	public static Capability<IEnergyStorage> CAPABILITY_FORGE_ENERGYSTORAGE = null;

	@Override
	public void update() {
		if (!world.isRemote) {
			buyPower();
			sendPower();
		}
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (stack != ItemStack.EMPTY) {
			if (stack.getCount() <= size) {
				setInventorySlotContents(slot, ItemStack.EMPTY);
			} else {
				stack = stack.splitStack(size);
				if (stack.getCount() == 0) {
					setInventorySlotContents(slot, ItemStack.EMPTY);
				}
			}
		}
		return stack;
	}

	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
		if (slot == itemCoinSlot) {
			int coinValue = 0;
			coinValue = CoinUtils.getCoinValue(stack);
			if (coinValue > 0) {
				int depositAmount = (int) Math.min(stack.getCount(), (Long.MAX_VALUE - coinSum) / coinValue);
				getStackInSlot(slot).shrink(depositAmount);
				coinSum += depositAmount * coinValue;
				if (getStackInSlot(slot).getCount() == 0) {
					inventory.set(slot, ItemStack.EMPTY);
				}
			}
		}
		if (slot == itemCardSlot && getStackInSlot(itemCardSlot).getItem() == UniversalCoins.Items.ender_card
				&& !world.isRemote && stack.hasTagCompound()) {
			String accountNumber = stack.getTagCompound().getString("Account");
			if (UniversalAccounts.getInstance().creditAccount(accountNumber, coinSum, false))
				coinSum = 0;
		}
	}

	@Override
	public String getName() {
		return UniversalCoins.Blocks.power_receiver.getLocalizedName();
	}

	@Override
	public boolean hasCustomName() {
		return false;
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public boolean isItemValidForSlot(int var1, ItemStack var2) {
		return false;
	}

	private boolean debitAccount(int i) {
		if (world.isRemote || getStackInSlot(itemCardSlot) == null || !getStackInSlot(itemCardSlot).hasTagCompound())
			return false;
		String accountNumber = getStackInSlot(itemCardSlot).getTagCompound().getString("Account");
		if (accountNumber == "") {
			return false;
		}
		return UniversalAccounts.getInstance().debitAccount(accountNumber, i, false);
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setLong("coinSum", coinSum);
		tagCompound.setInteger("feLevel", feLevel);
		tagCompound.setInteger("feOutput", feOutput);
		tagCompound.setLong("wfeLevel", wfeLevel);
		tagCompound.setString("blockOwner", blockOwner);
		if (orientation != null) {
			tagCompound.setInteger("orientation", orientation.ordinal());
		}
		tagCompound.setBoolean("publicAccess", publicAccess);

		return tagCompound;
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			coinSum = tagCompound.getLong("coinSum");
		} catch (Throwable ex2) {
			coinSum = 0;
		}
		try {
			feLevel = tagCompound.getInteger("feLevel");
		} catch (Throwable ex2) {
			feLevel = 0;
		}
		try {
			feOutput = tagCompound.getInteger("feOutput");
		} catch (Throwable ex2) {
			feOutput = 0;
		}
		try {
			wfeLevel = tagCompound.getLong("wfeLevel");
		} catch (Throwable ex2) {
			wfeLevel = 0;
		}
		try {
			blockOwner = tagCompound.getString("blockOwner");
		} catch (Throwable ex2) {
			blockOwner = "nobody";
		}
		try {
			orientation = EnumFacing.getFront(tagCompound.getInteger("orientation"));
		} catch (Throwable ex2) {
			orientation = null;
		}
		try {
			publicAccess = tagCompound.getBoolean("publicAccess");
		} catch (Throwable ex2) {
			publicAccess = false;
		}
	}

	public void onButtonPressed(int buttonId, boolean shift) {
		if (buttonId == PowerReceiverGUI.idCoinButton) {
			fillOutputSlot();
		}
		if (buttonId == PowerReceiverGUI.idAccessModeButton && blockOwner.matches(blockOwner)) {
			publicAccess ^= true;
		}
	}

	private void fillOutputSlot() {
		if (getStackInSlot(itemOutputSlot).isEmpty()) {
			if (coinSum >= UniversalCoins.coinValues[4]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.obsidian_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[4], 64));
				coinSum -= UniversalCoins.coinValues[4] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[3]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.diamond_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[3], 64));
				coinSum -= UniversalCoins.coinValues[3] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[2]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.emerald_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[2], 64));
				coinSum -= UniversalCoins.coinValues[2] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[1]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.gold_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[1], 64));
				coinSum -= UniversalCoins.coinValues[1] * getStackInSlot(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[0]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.iron_coin));
				getStackInSlot(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[0], 64));
				coinSum -= UniversalCoins.coinValues[0] * getStackInSlot(itemOutputSlot).getCount();
			}
		}
	}

	protected void buyPower() {
		if (feLevel == 0 && UniversalPower.getInstance().extractEnergy(10, true) > 0
				&& debitAccount(UniversalCoins.rfRetailRate)) {
			UniversalPower.getInstance().extractEnergy(10, false);
			feLevel += 10000;
		} else if (feLevel == 0 && UniversalPower.getInstance().extractEnergy(10, true) > 0
				&& coinSum - UniversalCoins.rfRetailRate >= 0) {
			coinSum -= UniversalCoins.rfRetailRate;
			UniversalPower.getInstance().extractEnergy(10, false);
			feLevel += 10000;
		}
		wfeLevel = UniversalPower.getInstance().getFeLevel();
	}

	protected void sendPower() {
		if (orientation == null) {
			resetPowerDirection();
			return;
		}
		feOutput = 0;
		TileEntity tile = world.getTileEntity(new BlockPos(pos.getX() + orientation.getFrontOffsetX(),
				pos.getY() + orientation.getFrontOffsetY(), pos.getZ() + orientation.getFrontOffsetZ()));
		if (tile != null) {
			IEnergyStorage energyStorage = tile.getCapability(CapabilityEnergy.ENERGY, orientation);
			if (energyStorage != null) {
				int maxFE = energyStorage.receiveEnergy(Math.min(1000, feLevel), true);
				feOutput = maxFE;
				feLevel -= energyStorage.receiveEnergy(maxFE, false);
			} else {
				orientation = null;
			}
		} else {
			orientation = null;
		}
	}

	protected void resetPowerDirection() {
		for (EnumFacing direction : EnumFacing.VALUES) {
			TileEntity tile = world.getTileEntity((new BlockPos(pos.getX() + direction.getFrontOffsetX(),
					pos.getY() + direction.getFrontOffsetY(), pos.getZ() + direction.getFrontOffsetZ())));
			if (tile != null && tile.hasCapability(CapabilityEnergy.ENERGY, direction)) {
				orientation = direction;
			}
		}
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.power_receiver.getLocalizedName());
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return getStackInSlot(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {
	}

	@Override
	public void closeInventory(EntityPlayer player) {
	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {
	}

	@Override
	public boolean isEmpty() {
		return false;
	}

	@Override
	public int receiveEnergy(int maxReceive, boolean simulate) {
		return 0;
	}

	@Override
	public int extractEnergy(int maxExtract, boolean simulate) {
		if (!simulate) {
			feLevel -= maxExtract;
			if (coinSum - UniversalCoins.rfRetailRate >= 0) {
				coinSum -= UniversalCoins.rfRetailRate;
			}
		}
		return Math.min(feLevel, 1000);
	}

	@Override
	public int getEnergyStored() {
		return feLevel;
	}

	@Override
	public int getMaxEnergyStored() {
		return Integer.MAX_VALUE;
	}

	@Override
	public boolean canExtract() {
		return feLevel > 0;
	}

	@Override
	public boolean canReceive() {
		return false;
	}

	@Override
	public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
		if (capability == CapabilityEnergy.ENERGY) {
			return true;
		}
		return super.hasCapability(capability, facing);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
		if (capability == CapabilityEnergy.ENERGY) {
			return (T) this;
		}
		return super.getCapability(capability, facing);
	}

	public boolean isUsableByPlayer(EntityPlayer player) {
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} public class TilePowerTransmitter extends TileProtected implements IInventory, IEnergyStorage {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack> withSize(2, ItemStack.EMPTY);
	public static final int itemCardSlot = 0;
	public static final int itemOutputSlot = 1;
	public long coinSum = 0;
	public int feLevel = 0;
	public int feOutput = 0;
	public int kfeSold = 0;
	public String blockOwner = "nobody";
	public boolean publicAccess;

	@CapabilityInject(IEnergyStorage.class)
	public static Capability<IEnergyStorage> CAPABILITY_FORGE_ENERGYSTORAGE = null;

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (stack != ItemStack.EMPTY) {
			if (stack.getCount() <= size) {
				setInventorySlotContents(slot, ItemStack.EMPTY);
			} else {
				stack = stack.splitStack(size);
				if (stack.getCount() == 0) {
					setInventorySlotContents(slot, ItemStack.EMPTY);
				}
			}
		}
		return stack;
	}

	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
		if (slot == itemCardSlot && inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card) {
			if (creditAccount(coinSum)) {
				coinSum = 0;
			}
		}
	}

	@Override
	public String getName() {
		return UniversalCoins.Blocks.power_transmitter.getLocalizedName();
	}

	@Override
	public boolean hasCustomName() {
		return false;
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public boolean isItemValidForSlot(int var1, ItemStack var2) {
		return false;
	}

	@SuppressWarnings("unused")
	private long getAccountBalance() {
		if (world.isRemote || inventory.get(itemCardSlot) == null || !inventory.get(itemCardSlot).hasTagCompound()) {
			return 0;
		}
		String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
		if (accountNumber == "") {
			return 0;
		}
		return UniversalAccounts.getInstance().getAccountBalance(accountNumber);
	}

	private boolean creditAccount(long amount) {
		if (world.isRemote || inventory.get(itemCardSlot) == ItemStack.EMPTY
				|| inventory.get(itemCardSlot).getItem() != UniversalCoins.Items.ender_card
				|| !inventory.get(itemCardSlot).hasTagCompound())
			return false;
		String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
		if (accountNumber == "") {
			return false;
		}
		return UniversalAccounts.getInstance().creditAccount(accountNumber, amount, false);
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setLong("coinSum", coinSum);
		tagCompound.setInteger("feLevel", feLevel);
		tagCompound.setInteger("kfeSold", kfeSold);
		tagCompound.setString("blockOwner", blockOwner);
		tagCompound.setBoolean("publicAccess", publicAccess);
		return tagCompound;
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack> withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			coinSum = tagCompound.getLong("coinSum");
		} catch (Throwable ex2) {
			coinSum = 0;
		}
		try {
			feLevel = tagCompound.getInteger("feLevel");
		} catch (Throwable ex2) {
			feLevel = 0;
		}
		try {
			kfeSold = tagCompound.getInteger("kfeSold");
		} catch (Throwable ex2) {
			kfeSold = 0;
		}
		try {
			blockOwner = tagCompound.getString("blockOwner");
		} catch (Throwable ex2) {
			blockOwner = "nobody";
		}
		try {
			publicAccess = tagCompound.getBoolean("publicAccess");
		} catch (Throwable ex2) {
			publicAccess = false;
		}
	}

	public void onButtonPressed(int buttonId, boolean shift) {
		if (buttonId == PowerTransmitterGUI.idCoinButton) {
			fillOutputSlot();
		}
		if (buttonId == PowerTransmitterGUI.idAccessModeButton && blockOwner.matches(blockOwner)) {
			publicAccess ^= true;
		}
	}

	private void fillOutputSlot() {
		if (inventory.get(itemOutputSlot).isEmpty()) {
			if (coinSum >= UniversalCoins.coinValues[4]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.obsidian_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[4], 64));
				coinSum -= UniversalCoins.coinValues[4] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[3]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.diamond_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[3], 64));
				coinSum -= UniversalCoins.coinValues[3] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[2]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.emerald_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[2], 64));
				coinSum -= UniversalCoins.coinValues[2] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[1]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.gold_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[1], 64));
				coinSum -= UniversalCoins.coinValues[1] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[0]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.iron_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[0], 64));
				coinSum -= UniversalCoins.coinValues[0] * inventory.get(itemOutputSlot).getCount();
			}
		}
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.power_transmitter.getLocalizedName());
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {

	}

	@Override
	public void closeInventory(EntityPlayer player) {

	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {

	}

	@Override
	public boolean isEmpty() {
		return false;
	}

	@Override
	public int receiveEnergy(int maxReceive, boolean simulate) {
		if (!simulate) {
			int rfChunks = 0;
			feLevel += maxReceive;
			if (feLevel >= 10000) {
				// calculate how many 10k chunks we can sell
				rfChunks = (int) Math.floor(feLevel / 10000);
				if (creditAccount(UniversalCoins.rfWholesaleRate * rfChunks)) {
					kfeSold += Math.min(10 * rfChunks, Integer.MAX_VALUE - kfeSold);
					UniversalPower.getInstance().receiveEnergy(10 * rfChunks, false);
					feLevel -= 10000 * rfChunks;
				} else if (coinSum + UniversalCoins.rfWholesaleRate * rfChunks <= Integer.MAX_VALUE) {
					coinSum += UniversalCoins.rfWholesaleRate * rfChunks;
					kfeSold += Math.min(10 * rfChunks, Integer.MAX_VALUE - kfeSold);
					UniversalPower.getInstance().receiveEnergy(10 * rfChunks, false);
					feLevel -= 10000 * rfChunks;
				}
			}
		}

		return maxReceive;
	}

	@Override
	public int extractEnergy(int maxExtract, boolean simulate) {
		return 0;
	}

	@Override
	public int getEnergyStored() {
		return feLevel;
	}

	@Override
	public int getMaxEnergyStored() {
		return Integer.MAX_VALUE;
	}

	@Override
	public boolean canExtract() {
		return false;
	}

	@Override
	public boolean canReceive() {
		return feLevel < Integer.MAX_VALUE;
	}

	@Override
	public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
		if (capability == CapabilityEnergy.ENERGY) {
			return true;
		}
		return super.hasCapability(capability, facing);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
		if (capability == CapabilityEnergy.ENERGY) {
			return (T) this;
		}
		return super.getCapability(capability, facing);
	}
	
	public boolean isUsableByPlayer(EntityPlayer player) {
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} public class TileProtected extends TileEntity {

	public String blockOwner = "none";
	public String playerName = "";
	public boolean inUse = false;

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		try {
			inUse = tagCompound.getBoolean("InUse");
		} catch (Throwable ex2) {
			inUse = false;
		}
		try {
			playerName = tagCompound.getString("playerName");
		} catch (Throwable ex2) {
			playerName = "none";
		}
		try {
			blockOwner = tagCompound.getString("blockOwner");
		} catch (Throwable ex2) {
			blockOwner = "none";
		}
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		tagCompound.setBoolean("InUse", inUse);
		tagCompound.setString("playerName", playerName);
		tagCompound.setString("blockOwner", blockOwner);
		return tagCompound;
	}

	// ==== chunk load sync ====//
	@Override
	public NBTTagCompound getUpdateTag() {
		NBTTagCompound nbt = new NBTTagCompound();
		this.writeToNBT(nbt);
		return nbt;
	}

	@Override
	public void handleUpdateTag(NBTTagCompound tag) {
		this.readFromNBT(tag);
	}
	// ==== /chunk load sync ====//

	// ===== block update sync =========//
	@Override
	public SPacketUpdateTileEntity getUpdatePacket() {
		return new SPacketUpdateTileEntity(this.pos, getBlockMetadata(), getUpdateTag());
	}

	@Override
	public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {
		readFromNBT(pkt.getNbtCompound());
	}

	public void updateTE() {
		final IBlockState state = getWorld().getBlockState(getPos());
		getWorld().notifyBlockUpdate(getPos(), state, state, 3);
	}
	// ===== /block update sync =========//

	// ==== general client to server messages ====/
	public void sendButtonMessage(int functionID, boolean shiftPressed) {
		UniversalCoins.snw
				.sendToServer(new UCButtonMessage(pos.getX(), pos.getY(), pos.getZ(), functionID, shiftPressed));
	}
	// ==== /general client to server messages ====/
} public class TileSafe extends TileProtected implements IInventory, ISidedInventory {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack> withSize(2, ItemStack.EMPTY);
	public static final int itemInputSlot = 0;
	public static final int itemOutputSlot = 1;
	public String blockOwner = "nobody";
	public String accountNumber = "0";
	public long accountBalance = 0;

	@Override
	public int[] getSlotsForFace(EnumFacing side) {
		return new int[] { 0 };
	}

	@Override
	public boolean canInsertItem(int index, ItemStack itemStack, EnumFacing direction) {
		if (index == 0) {
			Item itemInStack = itemStack.getItem();
			return (itemInStack == UniversalCoins.Items.iron_coin || itemInStack == UniversalCoins.Items.emerald_coin
					|| itemInStack == UniversalCoins.Items.gold_coin || itemInStack == UniversalCoins.Items.diamond_coin
					|| itemInStack == UniversalCoins.Items.obsidian_coin);
		}
		return false;
	}

	@Override
	public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) {
		return false;
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (stack != ItemStack.EMPTY) {
			if (stack.getCount() <= size) {
				setInventorySlotContents(slot, ItemStack.EMPTY);
			} else {
				stack = stack.splitStack(size);
				if (stack.getCount() == 0) {
					setInventorySlotContents(slot, ItemStack.EMPTY);
				}
			}
		}
		coinsTaken(stack);
		return stack;
	}

	public void coinsTaken(ItemStack stack) {
		int coinValue = 0;
		coinValue = CoinUtils.getCoinValue(stack);
		int debitAmount = 0;
		int accountCapacity = (int) (Long.MAX_VALUE - accountBalance > Integer.MAX_VALUE ? Integer.MAX_VALUE
				: Long.MAX_VALUE - accountBalance);
		debitAmount = Math.min(stack.getCount(), accountCapacity / coinValue);
		if (!world.isRemote) {
			UniversalAccounts.getInstance().debitAccount(accountNumber, debitAmount * coinValue, false);
			updateAccountBalance();
		}
		fillOutputSlot();
	}

	// @Override
	public ItemStack getStackInSlotOnClosing(int slot) {
		return getStackInSlot(slot);
	}

	@Override
	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
		int coinValue = 0;
		if (slot == itemInputSlot) {
			switch (stack.getUnlocalizedName()) {
			case "item.universalcoins.iron_coin":
				coinValue = UniversalCoins.coinValues[0];
				break;
			case "item.universalcoins.gold_coin":
				coinValue = UniversalCoins.coinValues[1];
				break;
			case "item.universalcoins.emerald_coin":
				coinValue = UniversalCoins.coinValues[2];
				break;
			case "item.universalcoins.diamond_coin":
				coinValue = UniversalCoins.coinValues[3];
				break;
			case "item.universalcoins.obsidian_coin":
				coinValue = UniversalCoins.coinValues[4];
				break;
			}
			if (coinValue > 0) {
				int accountCapacity = (int) (Long.MAX_VALUE - accountBalance > Integer.MAX_VALUE ? Integer.MAX_VALUE
						: Long.MAX_VALUE - accountBalance);
				int depositAmount = Math.min(accountCapacity / coinValue, stack.getCount());
				if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) {
					// Only deposit on server side, otherwise we deposit
					// twice.
					UniversalAccounts.getInstance().creditAccount(accountNumber, depositAmount * coinValue, false);
				}
				inventory.get(slot).shrink(depositAmount);
				if (inventory.get(slot).getCount() == 0) {
					inventory.set(slot, ItemStack.EMPTY);
				}
				fillOutputSlot();
				if (!world.isRemote)
					updateAccountBalance();
			}
		}
	}

	public void fillOutputSlot() {
		if (accountBalance > UniversalCoins.coinValues[4]) {
			inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.obsidian_coin));
			inventory.get(itemOutputSlot).setCount((int) Math.min(accountBalance / UniversalCoins.coinValues[4], 64));
		} else if (accountBalance > UniversalCoins.coinValues[3]) {
			inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.diamond_coin));
			inventory.get(itemOutputSlot).setCount((int) Math.min(accountBalance / UniversalCoins.coinValues[3], 64));
		} else if (accountBalance > UniversalCoins.coinValues[2]) {
			inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.emerald_coin));
			inventory.get(itemOutputSlot).setCount((int) Math.min(accountBalance / UniversalCoins.coinValues[2], 64));
		} else if (accountBalance > UniversalCoins.coinValues[1]) {
			inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.gold_coin));
			inventory.get(itemOutputSlot).setCount((int) Math.min(accountBalance / UniversalCoins.coinValues[1], 64));
		} else if (accountBalance > UniversalCoins.coinValues[0]) {
			inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.iron_coin));
			inventory.get(itemOutputSlot).setCount((int) Math.min(accountBalance / UniversalCoins.coinValues[0], 64));
		}
	}

	public void updateAccountBalance() {
		accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.safe.getLocalizedName());
	}

	@Override
	public boolean hasCustomName() {
		return false;
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public boolean isItemValidForSlot(int slot, ItemStack stack) {
		// we only have a coin input slot
		return true;
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setString("Owner", blockOwner);
		tagCompound.setString("AccountNumber", accountNumber);
		tagCompound.setLong("Balance", accountBalance);

		return tagCompound;
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack> withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			blockOwner = tagCompound.getString("Owner");
		} catch (Throwable ex2) {
			blockOwner = "nobody";
		}
		try {
			accountNumber = tagCompound.getString("AccountNumber");
		} catch (Throwable ex2) {
			accountNumber = "0";
		}
		try {
			accountBalance = tagCompound.getLong("Balance");
		} catch (Throwable ex2) {
			accountBalance = 0;
		}
	}

	public void setSafeAccount(String playerName) {
		accountNumber = UniversalAccounts.getInstance().getOrCreatePlayerAccount(getPlayerUID(playerName));
	}

	private String getPlayerUID(String playerName) {
		EntityPlayer player = world.getPlayerEntityByName(playerName);
		return player.getUniqueID().toString();
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {

	}

	@Override
	public void closeInventory(EntityPlayer player) {

	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {

	}

	@Override
	public String getName() {
		return UniversalCoins.Blocks.safe.getLocalizedName();
	}

	@Override
	public boolean isEmpty() {
		return false;
	}
	
	public boolean isUsableByPlayer(EntityPlayer player) {
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} public class TileSignal extends TileProtected implements IInventory, ITickable {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack> withSize(1, ItemStack.EMPTY);
	public static final int itemOutputSlot = 0;
	public String blockOwner = "";
	public int coinSum = 0;
	public int fee = 1;
	public int duration = 1;
	public int counter = 0;
	public int secondsLeft = 0;
	public int lastSecondsLeft = 0;
	public String customName = "";
	public boolean canProvidePower = false;

	@Override
	public void update() {
		if (!world.isRemote) {
			if (counter > 0) {
				counter--;
				secondsLeft = counter / 20;
				if (secondsLeft != lastSecondsLeft) {
					lastSecondsLeft = secondsLeft;
					updateTE();
				}
			} else {
				canProvidePower = false;
				updateTE();
				updateNeighbors();
			}
		}
	}

	public void onButtonPressed(int buttonId, boolean shift) {
		if (buttonId == 0) {
			fillOutputSlot();
		}
		if (buttonId == 1) {
			if (shift) {
				if (duration - 10 > 0) {
					duration -= 10;
				}
			} else {
				if (duration - 1 > 0) {
					duration--;
				}
			}
		}
		if (buttonId == 2) {
			if (shift) {
				if (duration + 10 < Integer.MAX_VALUE) {
					duration += 10;
				}
			} else {
				if (duration + 1 < Integer.MAX_VALUE) {
					duration++;
				}
			}
		}
		if (buttonId == 3) {
			if (shift) {
				if (fee - 10 > 0) {
					fee -= 10;
				}
			} else {
				if (fee - 1 > 0) {
					fee--;
				}
			}
		}
		if (buttonId == 4) {
			if (shift) {
				if (fee + 10 < Integer.MAX_VALUE) {
					fee += 10;
				}
			} else {
				if (fee + 1 < Integer.MAX_VALUE) {
					fee++;
				}
			}
		}
		updateTE();
	}

	public void activateSignal() {
		canProvidePower = true;
		counter += duration * 20;
		coinSum += fee;
		updateNeighbors();
	}

	private void updateNeighbors() {
		this.blockType = this.getBlockType();
		if (this.blockType instanceof BlockSignal) {
			((BlockSignal) blockType).updatePower(world, pos);
		}
	}

	public boolean isUsableByPlayer(EntityPlayer entityplayer) {
		return world.getTileEntity(pos) == this
				&& entityplayer.getDistanceSq(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) < 64;
	}

	public String getName() {
		return this.hasCustomName() ? this.customName : UniversalCoins.Blocks.signalblock.getLocalizedName();
	}

	public void setName(String name) {
		customName = name;
	}

	public boolean isInventoryNameLocalized() {
		return false;
	}

	@Override
	public boolean hasCustomName() {
		return this.customName != null && this.customName.length() > 0;
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setString("blockOwner", blockOwner);
		tagCompound.setInteger("coinSum", coinSum);
		tagCompound.setInteger("fee", fee);
		tagCompound.setInteger("duration", duration);
		tagCompound.setInteger("secondsLeft", secondsLeft);
		tagCompound.setString("customName", customName);
		tagCompound.setBoolean("canProvidePower", canProvidePower);
		return tagCompound;
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack> withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			blockOwner = tagCompound.getString("blockOwner");
		} catch (Throwable ex2) {
			blockOwner = "";
		}
		try {
			coinSum = tagCompound.getInteger("coinSum");
		} catch (Throwable ex2) {
			coinSum = 0;
		}
		try {
			fee = tagCompound.getInteger("fee");
		} catch (Throwable ex2) {
			fee = 1;
		}
		try {
			duration = tagCompound.getInteger("duration");
		} catch (Throwable ex2) {
			duration = 1;
		}
		try {
			secondsLeft = tagCompound.getInteger("secondsLeft");
		} catch (Throwable ex2) {
			secondsLeft = 0;
		}
		try {
			customName = tagCompound.getString("customName");
		} catch (Throwable ex2) {
			customName = "";
		}
		try {
			canProvidePower = tagCompound.getBoolean("canProvidePower");
		} catch (Throwable ex2) {
			canProvidePower = false;
		}
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (stack != ItemStack.EMPTY) {
			if (stack.getCount() <= size) {
				inventory.set(slot, ItemStack.EMPTY);
			} else {
				stack = stack.splitStack(size);
				if (stack.getCount() == 0) {
					inventory.set(slot, ItemStack.EMPTY);
				}
			}
		}
		return stack;
	}

	private void fillOutputSlot() {
		if (inventory.get(itemOutputSlot).isEmpty()) {
			if (coinSum >= UniversalCoins.coinValues[4]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.obsidian_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[4], 64));
				coinSum -= UniversalCoins.coinValues[4] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[3]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.diamond_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[3], 64));
				coinSum -= UniversalCoins.coinValues[3] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[2]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.emerald_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[2], 64));
				coinSum -= UniversalCoins.coinValues[2] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[1]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.gold_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[1], 64));
				coinSum -= UniversalCoins.coinValues[1] * inventory.get(itemOutputSlot).getCount();
			} else if (coinSum >= UniversalCoins.coinValues[0]) {
				inventory.set(itemOutputSlot, new ItemStack(UniversalCoins.Items.iron_coin));
				inventory.get(itemOutputSlot).setCount((int) Math.min(coinSum / UniversalCoins.coinValues[0], 64));
				coinSum -= UniversalCoins.coinValues[0] * inventory.get(itemOutputSlot).getCount();
			}
		}
	}

	// @Override
	public ItemStack getStackInSlotOnClosing(int i) {
		return getStackInSlot(i);
	}

	@Override
	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public boolean isItemValidForSlot(int var1, ItemStack var2) {
		return false;
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {
	}

	@Override
	public void closeInventory(EntityPlayer player) {
	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {

	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.signalblock.getLocalizedName());
	}

	@Override
	public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) {
		return false;
	}

	@Override
	public boolean isEmpty() {
		return false;
	}
} public class TileTradeStation extends TileProtected implements IInventory, ISidedInventory {
	private NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(4, ItemStack.EMPTY);
	public static final int itemInputSlot = 0;
	public static final int itemOutputSlot = 1;
	public static final int itemCardSlot = 2;
	public static final int itemCoinSlot = 3;
	public int coinSum = 0;
	public int itemPrice = 0;
	public boolean buyButtonActive = false;
	public boolean sellButtonActive = false;
	public boolean ironCoinBtnActive = false;
	public boolean goldCoinBtnActive = false;
	public boolean emeraldCoinBtnActive = false;
	public boolean diamondCoinBtnActive = false;
	public boolean obsidianCoinBtnActive = false;
	public boolean autoModeButtonActive = UniversalCoins.autoModeEnabled;
	public boolean publicAccess = true;

	public int autoMode = 0;
	private int autoDelayCounter = 0;
	public int coinMode = 0;

	public TileTradeStation() {
		super();
	}

	public void update() {
		activateBuySellButtons();
		activateRetrieveButtons();

		if (!world.isRemote) {
			// runAutoMode();
			runCoinMode();
		}
	}

	public void inUseCleanup() {
		inUse = false;
	}

	private void activateBuySellButtons() {
		if (getStackInSlot(itemInputSlot) == ItemStack.EMPTY) {
			itemPrice = 0;
			buyButtonActive = false;
			sellButtonActive = false;
		} else {
			itemPrice = UCItemPricer.getInstance().getItemPrice(getStackInSlot(itemInputSlot));
			if (itemPrice <= -1 || itemPrice == 0) {
				itemPrice = 0;
				buyButtonActive = false;
				sellButtonActive = false;
			} else {
				sellButtonActive = true;
				// disable sell button if coinSum is near max
				if (Integer.MAX_VALUE - coinSum < itemPrice) {
					sellButtonActive = false;
				}
				buyButtonActive = (UniversalCoins.tradeStationBuyEnabled
						&& (inventory.get(itemOutputSlot).isEmpty()
								|| (inventory.get(itemOutputSlot)).getItem() == inventory.get(itemInputSlot).getItem()
										&& inventory.get(itemOutputSlot).getCount() < inventory.get(itemInputSlot)
												.getMaxStackSize()
										&& !UCItemPricer.getInstance().hasEnchantment(inventory.get(itemOutputSlot)))
						&& (coinSum >= itemPrice || (!inventory.get(itemCardSlot).isEmpty() && !world.isRemote
								&& getAccountBalance() >= itemPrice)));
			}
		}
	}

	private void activateRetrieveButtons() {
		ironCoinBtnActive = false;
		goldCoinBtnActive = false;
		emeraldCoinBtnActive = false;
		diamondCoinBtnActive = false;
		obsidianCoinBtnActive = false;
		if (coinSum > 0) {
			ironCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.iron_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[1]) {
			goldCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.gold_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[2]) {
			emeraldCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.emerald_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[3]) {
			diamondCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.diamond_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[4]) {
			obsidianCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.obsidian_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
	}

	public void onSellPressed() {
		onSellPressed(1);
	}

	private void onSellPressed(int amount) {
		if (inventory.get(itemInputSlot).isEmpty()) {
			sellButtonActive = false;
			return;
		}
		if (amount > inventory.get(itemInputSlot).getCount()) {
			return;
		}
		itemPrice = UCItemPricer.getInstance().getItemPrice(inventory.get(itemInputSlot));
		if (itemPrice == -1) {
			sellButtonActive = false;
			return;
		}
		// handle damaged items
		if (inventory.get(itemInputSlot).isItemDamaged()) {
			itemPrice = itemPrice
					* (inventory.get(itemInputSlot).getMaxDamage() - inventory.get(itemInputSlot).getItemDamage())
					/ inventory.get(itemInputSlot).getMaxDamage();
		}
		inventory.get(itemInputSlot).shrink(amount);
		if (inventory.get(itemInputSlot).getCount() <= 0) {
			inventory.set(itemInputSlot, ItemStack.EMPTY);
		}
		int coinFromSale = (int) (itemPrice * amount * UniversalCoins.itemSellRatio);
		if (!inventory.get(itemCardSlot).isEmpty()
				&& inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card
				&& getAccountBalance() + (itemPrice * amount * UniversalCoins.itemSellRatio) < Long.MAX_VALUE) {
			creditAccount(coinFromSale);
		} else {
			coinSum += coinFromSale;
		}
		this.updateTE();
	}

	public void onSellMaxPressed() {
		int amount = 0;
		if (inventory.get(itemInputSlot).isEmpty()) {
			sellButtonActive = false;
			return;
		}
		itemPrice = UCItemPricer.getInstance().getItemPrice(inventory.get(itemInputSlot));
		if (itemPrice == -1 || itemPrice == 0) {
			sellButtonActive = false;
			return;
		}
		amount = (int) Math.min(inventory.get(itemInputSlot).getCount(),
				Math.min((Integer.MAX_VALUE - coinSum) / itemPrice, Integer.MAX_VALUE / itemPrice));
		if (amount > 0) {
			onSellPressed(amount);
		}
	}

	public void onBuyPressed() {
		onBuyPressed(1);
	}

	private void onBuyPressed(int amount) {
		boolean useCard = false;
		if (inventory.get(itemInputSlot).isEmpty() || !UniversalCoins.tradeStationBuyEnabled) {
			buyButtonActive = false;
			return;
		}
		itemPrice = UCItemPricer.getInstance().getItemPrice(inventory.get(itemInputSlot));
		// use the card if we have it
		if (!inventory.get(itemCardSlot).isEmpty() && getAccountBalance() > itemPrice * amount) {
			useCard = true;
		}
		if (itemPrice == -1 || (coinSum < itemPrice * amount && !useCard)) {
			// not enough coins, do we have a card?
			buyButtonActive = false;
			return;
		}
		if (inventory.get(itemOutputSlot).isEmpty() && inventory.get(itemInputSlot).getMaxStackSize() >= amount) {
			if (!debitAccount(itemPrice * amount)) {
				coinSum -= itemPrice * amount;
			}
			if (inventory.get(itemInputSlot).isItemStackDamageable()) {
				inventory.set(itemOutputSlot, new ItemStack(inventory.get(itemInputSlot).getItem(), amount, 0));
			} else {
				inventory.set(itemOutputSlot, new ItemStack(inventory.get(itemInputSlot).getItem(), amount,
						inventory.get(itemInputSlot).getItemDamage()));
			}
			if (UCItemPricer.getInstance().hasEnchantment(inventory.get(itemInputSlot))
					|| UCItemPricer.getInstance().hasPotion(inventory.get(itemInputSlot))) {
				inventory.get(itemOutputSlot).setTagCompound(inventory.get(itemInputSlot).getTagCompound());
			}
		} else if (inventory.get(itemOutputSlot).getItem() == inventory.get(itemInputSlot).getItem()
				&& inventory.get(itemOutputSlot).getItemDamage() == inventory.get(itemInputSlot).getItemDamage()
				&& inventory.get(itemOutputSlot).getCount() + amount <= inventory.get(itemInputSlot)
						.getMaxStackSize()) {
			if (!debitAccount(itemPrice * amount)) {
				coinSum -= itemPrice * amount;
			}
			inventory.get(itemOutputSlot).grow(amount);
		} else {
			buyButtonActive = false;
		}
		this.updateTE();
	}

	public void onBuyMaxPressed() {
		boolean useCard = false;
		int amount = 0;
		itemPrice = UCItemPricer.getInstance().getItemPrice(inventory.get(itemInputSlot));
		// use the card if we have it
		if (!inventory.get(itemCardSlot).isEmpty() && getAccountBalance() > itemPrice) {
			useCard = true;
		}
		if (itemPrice == -1 || (coinSum < itemPrice && !useCard)) {
			buyButtonActive = false;
			return;
		}
		if (inventory.get(itemOutputSlot).isEmpty()) {
			if (inventory.get(itemInputSlot).getMaxStackSize()
					* itemPrice <= (useCard ? getAccountBalance() : coinSum)) {
				amount = inventory.get(itemInputSlot).getMaxStackSize();
			} else {
				amount = (int) ((useCard ? getAccountBalance() : coinSum) / itemPrice);
			}
		} else if (inventory.get(itemOutputSlot).getItem() == inventory.get(itemInputSlot).getItem()
				&& inventory.get(itemOutputSlot).getItemDamage() == inventory.get(itemInputSlot).getItemDamage()
				&& inventory.get(itemOutputSlot).getCount() < inventory.get(itemInputSlot).getMaxStackSize()) {
			if ((inventory.get(itemOutputSlot).getMaxStackSize() - inventory.get(itemOutputSlot).getCount())
					* itemPrice <= (useCard ? getAccountBalance() : coinSum)) {
				amount = inventory.get(itemOutputSlot).getMaxStackSize() - inventory.get(itemOutputSlot).getCount();
			} else {
				amount = (int) ((useCard ? getAccountBalance() : coinSum) / itemPrice);
			}
		} else {
			buyButtonActive = false;
		}
		onBuyPressed(amount);
	}

	public void onAutoModeButtonPressed() {
		if (autoMode == 2) {
			autoMode = 0;
		} else {
			autoMode++;
			if (autoMode == 1 && !UniversalCoins.tradeStationBuyEnabled) {
				autoMode++;
			}
		}
	}

	public void onCoinModeButtonPressed() {
		if (coinMode == 0) {
			coinMode = 5;
		} else
			coinMode--;
	}

	public void runAutoMode() {
		// Delay autosell to workaround thermal expansion's auto output issue
		if (autoDelayCounter == 3) {
			autoDelayCounter = 0;
			if (autoMode == 0) {
				return;
			} else if (autoMode == 1) {
				onBuyMaxPressed();
			} else if (autoMode == 2) {
				onSellMaxPressed();
			}
		}
		autoDelayCounter++;
	}

	public void runCoinMode() {
		if (coinMode == 0) {
			return;
		} else {
			onRetrieveButtonsPressed(coinMode + 1, true);
		}
	}

	public void onRetrieveButtonsPressed(int buttonClickedID, boolean shiftPressed) {
		int absoluteButton = buttonClickedID - TradeStationGUI.idCoinButton;
		Item itemOnButton = null;
		switch (absoluteButton) {
		case 0:
			itemOnButton = UniversalCoins.Items.iron_coin;
			break;
		case 1:
			itemOnButton = UniversalCoins.Items.gold_coin;
			break;
		case 2:
			itemOnButton = UniversalCoins.Items.emerald_coin;
			break;
		case 3:
			itemOnButton = UniversalCoins.Items.diamond_coin;
			break;
		case 4:
			itemOnButton = UniversalCoins.Items.obsidian_coin;
			break;
		}
		if (itemOnButton == null)
			return;
		if (coinSum < UniversalCoins.coinValues[absoluteButton]
				|| (!inventory.get(itemOutputSlot).isEmpty() && inventory.get(itemOutputSlot).getItem() != itemOnButton)
				|| (!inventory.get(itemOutputSlot).isEmpty() && inventory.get(itemOutputSlot).getCount() == 64)) {
			return;
		}
		if (shiftPressed) {
			if (inventory.get(itemOutputSlot).isEmpty()) {
				int amount = (int) (coinSum / UniversalCoins.coinValues[absoluteButton]);
				if (amount >= 64) {
					coinSum -= UniversalCoins.coinValues[absoluteButton] * 64;
					inventory.set(itemOutputSlot, new ItemStack(itemOnButton));
					inventory.get(itemOutputSlot).setCount(64);
				} else {
					coinSum -= UniversalCoins.coinValues[absoluteButton] * amount;
					inventory.set(itemOutputSlot, new ItemStack(itemOnButton));
					inventory.get(itemOutputSlot).setCount(amount);
				}
			} else {
				int amount = (int) Math.min(coinSum / UniversalCoins.coinValues[absoluteButton],
						inventory.get(itemOutputSlot).getMaxStackSize() - inventory.get(itemOutputSlot).getCount());
				inventory.get(itemOutputSlot).grow(amount);
				coinSum -= UniversalCoins.coinValues[absoluteButton] * amount;
			}
		} else {
			coinSum -= UniversalCoins.coinValues[absoluteButton];
			if (inventory.get(itemOutputSlot).isEmpty()) {
				inventory.set(itemOutputSlot, new ItemStack(itemOnButton));
			} else {
				inventory.get(itemOutputSlot).grow(1);
			}
		}
	}

	public void onButtonPressed(int buttonId, boolean shiftPressed) {
		if (buttonId == TradeStationGUI.idBuyButton) {
			if (shiftPressed) {
				onBuyMaxPressed();
			} else {
				onBuyPressed();
			}
		} else if (buttonId == TradeStationGUI.idSellButton) {
			if (shiftPressed) {
				onSellMaxPressed();
			} else {
				onSellPressed();
			}
		} else if (buttonId == TradeStationGUI.idAutoModeButton) {
			onAutoModeButtonPressed();
		} else if (buttonId == TradeStationGUI.idCoinModeButton) {
			onCoinModeButtonPressed();
		} else if (buttonId <= TradeStationGUI.idLBagButton) {
			onRetrieveButtonsPressed(buttonId, shiftPressed);
		} else if (buttonId == TradeStationGUI.idAccessModeButton && blockOwner.matches(playerName)) {
			publicAccess ^= true;
		}
		update();
	}

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			autoMode = tagCompound.getInteger("AutoMode");
		} catch (Throwable ex2) {
			autoMode = 0;
		}
		try {
			coinMode = tagCompound.getInteger("CoinMode");
		} catch (Throwable ex2) {
			coinMode = 0;
		}
		try {
			coinSum = tagCompound.getInteger("CoinSum");
		} catch (Throwable ex2) {
			coinSum = 0;
		}
		try {
			autoModeButtonActive = tagCompound.getBoolean("AutoModeButtonActive");
		} catch (Throwable ex2) {
			autoModeButtonActive = true;
		}
		try {
			inUse = tagCompound.getBoolean("InUse");
		} catch (Throwable ex2) {
			inUse = false;
		}
		try {
			publicAccess = tagCompound.getBoolean("PublicAccess");
		} catch (Throwable ex2) {
			publicAccess = true;
		}
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		new NBTTagList();
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setInteger("AutoMode", autoMode);
		tagCompound.setInteger("CoinMode", coinMode);
		tagCompound.setInteger("CoinSum", coinSum);
		tagCompound.setBoolean("AutoModeButtonActive", autoModeButtonActive);
		tagCompound.setBoolean("InUse", inUse);
		tagCompound.setBoolean("PublicAccess", publicAccess);
		return tagCompound;
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public String getName() {
		return UniversalCoins.Blocks.tradestation.getLocalizedName();
	}

	public void setName(String name) {
	}

	public boolean isNameLocalized() {
		return false;
	}

	@Override
	public boolean hasCustomName() {
		return false;
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		runAutoMode();
		return (ItemStack) inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack itemstack = ItemStackHelper.getAndSplit(inventory, slot, size);
		if (!itemstack.isEmpty()) {
			this.markDirty();
		}
		return itemstack;
	}

	// @Override
	public ItemStack getStackInSlotOnClosing(int index) {
		inUse = false;
		return (ItemStack) inventory.get(index);
	}

	@Override
	public void setInventorySlotContents(int slot, ItemStack stack) {
		autoDelayCounter = 0;
		inventory.set(slot, stack);
		if (slot == itemCoinSlot || slot == itemInputSlot) {
			int coinValue = 0;
			coinValue = CoinUtils.getCoinValue(stack);
			if (coinValue > 0) {
				int depositAmount = (int) Math.min(Integer.MAX_VALUE - coinSum / coinValue, stack.getCount());
				if (inventory.get(itemCardSlot) != null && inventory.get(itemCardSlot).hasTagCompound()
						&& inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card) {
					creditAccount(depositAmount * coinValue);
				} else {
					coinSum += depositAmount * coinValue;
				}
				ItemStack newStack = stack;
				newStack.shrink((int) depositAmount);
				if (!newStack.isEmpty()) {
					inventory.set(slot, newStack);
				} else {
					inventory.set(slot, ItemStack.EMPTY);
				}
			}
		}
		if (slot == itemCardSlot && inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card) {
			if (!world.isRemote) {
				String accountNumber = stack.getTagCompound().getString("Account");
				if (UniversalAccounts.getInstance().creditAccount(accountNumber, coinSum, false)) {
					coinSum = 0;
				}
			}
		}
		update();
	}

	/**
	 * Returns true if automation is allowed to insert the given stack (ignoring
	 * stack size) into the given slot.
	 */
	@Override
	public boolean isItemValidForSlot(int slot, ItemStack itemstack) {
		Item stackItem = itemstack.getItem();
		if (slot == itemCoinSlot) {
			return stackItem == UniversalCoins.Items.iron_coin || stackItem == UniversalCoins.Items.gold_coin
					|| stackItem == UniversalCoins.Items.emerald_coin || stackItem == UniversalCoins.Items.diamond_coin
					|| stackItem == UniversalCoins.Items.obsidian_coin;
		} else {
			return slot == itemInputSlot;
		}
	}

	@Override
	public int[] getSlotsForFace(EnumFacing side) {
		return new int[] { 0, 1, 2, 3 };
	}

	@Override
	public boolean canInsertItem(int index, ItemStack stack, EnumFacing direction) {
		// first check if items inserted are coins. put them in the coin input
		// slot if they are.
		if (index == itemCoinSlot && (stack.getItem() == (UniversalCoins.Items.iron_coin)
				|| stack.getItem() == (UniversalCoins.Items.gold_coin)
				|| stack.getItem() == (UniversalCoins.Items.emerald_coin)
				|| stack.getItem() == (UniversalCoins.Items.diamond_coin)
				|| stack.getItem() == (UniversalCoins.Items.obsidian_coin))) {
			return true;
			// put everything else in the item input slot
		} else if (index == itemInputSlot) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public boolean canExtractItem(int index, ItemStack stack, EnumFacing direction) {
		// allow pulling items from output slot only
		if (index == itemOutputSlot) {
			return true;
		} else {
			return false;
		}
	}

	public long getAccountBalance() {
		if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound()) {
			String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			return UniversalAccounts.getInstance().getAccountBalance(accountNumber);
		}
		return -1;
	}

	public boolean debitAccount(int amount) {
		if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound()) {
			String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			return UniversalAccounts.getInstance().debitAccount(accountNumber, amount, false);
		}
		return false;
	}

	public boolean creditAccount(int amount) {
		if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound()) {
			String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			return UniversalAccounts.getInstance().creditAccount(accountNumber, amount, false);
		}
		return false;
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public void openInventory(EntityPlayer player) {
	}

	@Override
	public void closeInventory(EntityPlayer player) {
	}

	@Override
	public int getField(int id) {
		switch (id) {
		case 0:
			return coinSum;
		case 1:
			return itemPrice;
		case 2:
			return autoMode;
		case 3:
			return coinMode;
		case 4:
			return publicAccess == true ? 1 : 0;
		case 5:
			return buyButtonActive == true ? 1 : 0;
		default:
			return 0;
		}
	}

	@Override
	public void setField(int id, int value) {
		switch (id) {
		case 0:
			coinSum = value;
			break;
		case 1:
			itemPrice = value;
			break;
		case 2:
			autoMode = value;
			break;
		case 3:
			coinMode = value;
			break;
		case 4:
			publicAccess = value == 1 ? true : false;
			break;
		case 5:
			buyButtonActive = value == 1 ? true : false;
			break;
		default:
			break;
		}
	}

	@Override
	public int getFieldCount() {
		return 6;
	}

	@Override
	public void clear() {

	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.tradestation.getLocalizedName());
	}

	@Override
	public boolean isEmpty() {
		for (ItemStack itemstack : this.inventory) {
			if (!itemstack.isEmpty()) {
				return false;
			}
		}
		return true;
	}

	@Override
	public boolean isUsableByPlayer(EntityPlayer player) {
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} public class TileUCSign extends TileEntitySign {

	public String blockOwner = "";

	@Override
	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);

		for (int i = 0; i < 4; ++i) {
			String s = tagCompound.getString("Text" + (i + 1));
			ITextComponent itextcomponent = ITextComponent.Serializer.jsonToComponent(s);

			this.signText[i] = itextcomponent;

			try {
				blockOwner = tagCompound.getString("blockOwner");
			} catch (Throwable ex) {
				blockOwner = "";
			}
		}
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);

		for (int i = 0; i < 4; ++i) {
			String s = ITextComponent.Serializer.componentToJson(this.signText[i]);
			tagCompound.setString("Text" + (i + 1), s);
		}

		tagCompound.setString("blockOwner", blockOwner);
		return tagCompound;
	}

	public void updateSign() {
		final IBlockState state = getWorld().getBlockState(getPos());
		getWorld().notifyBlockUpdate(getPos(), state, state, 3);
	}

	public void sendServerUpdateMessage() {
		UniversalCoins.snw.sendToServer(new UCSignServerMessage(pos.getX(), pos.getY(), pos.getZ(), signText));
	}

	@Override
	public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {
		readFromNBT(pkt.getNbtCompound());
	}

	@Nullable
	@Override
	public SPacketUpdateTileEntity getUpdatePacket() {
		return new SPacketUpdateTileEntity(this.pos, 9, this.getUpdateTag());
	}

	@Override
	public NBTTagCompound getUpdateTag() {
		return this.writeToNBT(new NBTTagCompound());
	}

	public void scanChestContents(IBlockState state, BlockPos fromPos) {
		TileEntity tileEntity = world.getTileEntity(fromPos);
		String[] itemName = { "", "", "", "" };
		int[] itemCount = { 0, 0, 0, 0 };
		if (tileEntity != null && tileEntity instanceof IInventory) {
			IInventory inventory = (IInventory) tileEntity;
			for (int i = 0; i < inventory.getSizeInventory(); i++) {
				ItemStack stack = inventory.getStackInSlot(i);
				if (stack != null) {
					for (int j = 0; j < itemName.length; j++) {
						if (itemName[j] == "") {
							if (!itemName[0].matches(inventory.getStackInSlot(i).getDisplayName())
									&& !itemName[1].matches(inventory.getStackInSlot(i).getDisplayName())
									&& !itemName[2].matches(inventory.getStackInSlot(i).getDisplayName())
									&& !itemName[3].matches(inventory.getStackInSlot(i).getDisplayName())) {
								itemName[j] = inventory.getStackInSlot(i).getDisplayName();
							}
						}
						if (itemName[j].contentEquals(inventory.getStackInSlot(i).getDisplayName())) {
							if (itemName[j].contentEquals("Air")) {
								itemCount[j]++;
							}
							itemCount[j] += inventory.getStackInSlot(i).getCount();
						}
					}
				}
			}
			// if we have a double chest, scan it too
			if (tileEntity instanceof TileEntityChest) {
				TileEntity tileEntity2 = null;
				if (((TileEntityChest) tileEntity).adjacentChestXNeg != null)
					tileEntity2 = (((TileEntityChest) tileEntity).adjacentChestXNeg);
				if (((TileEntityChest) tileEntity).adjacentChestXPos != null)
					tileEntity2 = (((TileEntityChest) tileEntity).adjacentChestXPos);
				if (((TileEntityChest) tileEntity).adjacentChestZNeg != null)
					tileEntity2 = (((TileEntityChest) tileEntity).adjacentChestZNeg);
				if (((TileEntityChest) tileEntity).adjacentChestZPos != null)
					tileEntity2 = (((TileEntityChest) tileEntity).adjacentChestZPos);
				if (tileEntity2 != null) {
					inventory = (IInventory) tileEntity2;
					for (int i = 0; i < inventory.getSizeInventory(); i++) {
						ItemStack stack = inventory.getStackInSlot(i);
						if (stack != null) {
							for (int j = 0; j < itemName.length; j++) {
								if (itemName[j] == "") {
									if (!itemName[0].matches(inventory.getStackInSlot(i).getDisplayName())
											&& !itemName[1].matches(inventory.getStackInSlot(i).getDisplayName())
											&& !itemName[2].matches(inventory.getStackInSlot(i).getDisplayName())
											&& !itemName[3].matches(inventory.getStackInSlot(i).getDisplayName())) {
										itemName[j] = inventory.getStackInSlot(i).getDisplayName();
									}
								}
								if (itemName[j].contentEquals(inventory.getStackInSlot(i).getDisplayName())) {
									if (itemName[j].contentEquals("Air")) {
										itemCount[j]++;
									}
									itemCount[j] += inventory.getStackInSlot(i).getCount();
								}
							}
						}
					}
				}
			}

			// update sign with info collected
			for (int i = 0; i < itemName.length; i++) {
				if (itemName[i].contentEquals("Air")) {
					signText[i] = new TextComponentString(itemCount[i] + " Empty Slots");

				} else if (!itemName[i].contentEquals("")) {
					signText[i] = new TextComponentString(itemCount[i] + " " + itemName[i]);
				} else {
					{
						signText[i] = new TextComponentString("");
					}
					this.updateSign();
				}
			}
		}
	}
} public class TileVendor extends TileProtected implements IInventory {
	protected NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(17, ItemStack.EMPTY);
	// owner slots
	public static final int itemStorageSlot1 = 0;
	public static final int itemStorageSlot2 = 1;
	public static final int itemStorageSlot3 = 2;
	public static final int itemStorageSlot4 = 3;
	public static final int itemStorageSlot5 = 4;
	public static final int itemStorageSlot6 = 5;
	public static final int itemStorageSlot7 = 6;
	public static final int itemStorageSlot8 = 7;
	public static final int itemStorageSlot9 = 8;
	public static final int itemTradeSlot = 9;
	public static final int itemCardSlot = 10;
	// sale slots
	public static final int itemSellSlot = 11;
	public static final int itemOutputSlot = 12;
	public static final int itemCoinOutputSlot = 13;
	public static final int itemCoinInputSlot = 14;
	public static final int itemUserCoinInputSlot = 15;
	// card slot
	public static final int itemUserCardSlot = 16;

	public int coinSum = 0;
	public int userCoinSum = 0;
	public int itemPrice = 0;
	public boolean infiniteMode = false;
	public boolean sellMode = true;
	public boolean ooStockWarning = false;
	public boolean ooCoinsWarning = false;
	public boolean inventoryFullWarning = false;
	public boolean buyButtonActive = false;
	public boolean sellButtonActive = false;
	public boolean ironCoinBtnActive = false;
	public boolean goldCoinBtnActive = false;
	public boolean emeraldCoinBtnActive = false;
	public boolean diamondCoinBtnActive = false;
	public boolean obsidianCoinBtnActive = false;
	public boolean usellButtonActive = false;
	public boolean uironCoinBtnActive = false;
	public boolean ugoldCoinBtnActive = false;
	public boolean uemeraldCoinBtnActive = false;
	public boolean udiamondCoinBtnActive = false;
	public boolean uobsidianCoinBtnActive = false;
	public int textColor = 0x0;
	private int remoteX = 0;
	private int remoteY = 0;
	private int remoteZ = 0;

	public void update() {
		if (!world.isRemote) {
			activateRetrieveButtons();
			activateUserRetrieveButtons();
			activateBuyButton();
			activateSellButton();
			if (ooStockWarning)
				checkRemoteStorage();
		}
	}

	public void inUseCleanup() {
		if (world.isRemote)
			return;
		inUse = false;
	}

	private void activateBuyButton() {
		if ((userCoinSum >= itemPrice && coinSum + itemPrice < Integer.MAX_VALUE && (!ooStockWarning || infiniteMode))
				|| (!inventory.get(itemUserCardSlot).isEmpty() && getUserAccountBalance() > itemPrice
						&& (!ooStockWarning || infiniteMode))) {
			if (inventory.get(itemOutputSlot).isEmpty()) {
				if (inventory.get(itemOutputSlot).getMaxStackSize() == inventory.get(itemOutputSlot).getCount()) {
					buyButtonActive = false;
					return;
				}
			}
			buyButtonActive = true;
		} else
			buyButtonActive = false;
	}

	private void activateSellButton() {
		if (!inventory.get(itemSellSlot).isEmpty()
				&& inventory.get(itemTradeSlot).getItem() == inventory.get(itemSellSlot).getItem()
				&& (hasInventorySpace() && (getOwnerAccountBalance() >= itemPrice || coinSum >= itemPrice)
						|| infiniteMode)) {
			sellButtonActive = true;
		} else
			sellButtonActive = false;
	}

	private void activateRetrieveButtons() {
		ironCoinBtnActive = false;
		goldCoinBtnActive = false;
		emeraldCoinBtnActive = false;
		diamondCoinBtnActive = false;
		obsidianCoinBtnActive = false;
		if (coinSum > 0) {
			ironCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.iron_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[1]) {
			goldCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.gold_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[2]) {
			emeraldCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.emerald_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[3]) {
			diamondCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.diamond_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
		if (coinSum >= UniversalCoins.coinValues[4]) {
			obsidianCoinBtnActive = inventory.get(itemOutputSlot).isEmpty()
					|| (inventory.get(itemOutputSlot).getItem() == UniversalCoins.Items.obsidian_coin
							&& inventory.get(itemOutputSlot).getCount() != 64);
		}
	}

	public void onRetrieveButtonsPressed(int buttonClickedID, boolean shiftPressed) {
		if (buttonClickedID <= VendorGUI.idObsidianCoinBtn) {
			// get owner coins
			coinSum = retrieveCoins(coinSum, buttonClickedID, shiftPressed);
			updateCoinsForPurchase();
		} else {
			// get buyer coins
			userCoinSum = retrieveCoins(userCoinSum, buttonClickedID, shiftPressed);
		}
		update();
	}

	public int retrieveCoins(int coinField, int buttonClickedID, boolean shiftPressed) {
		int absoluteButton = 0;
		if (buttonClickedID > 9) {
			absoluteButton = buttonClickedID - 12;
		} else {
			absoluteButton = buttonClickedID - 3;
		}
		Item itemOnButton = null;
		switch (absoluteButton) {
		case 0:
			itemOnButton = UniversalCoins.Items.iron_coin;
			break;
		case 1:
			itemOnButton = UniversalCoins.Items.gold_coin;
			break;
		case 2:
			itemOnButton = UniversalCoins.Items.emerald_coin;
			break;
		case 3:
			itemOnButton = UniversalCoins.Items.diamond_coin;
			break;
		case 4:
			itemOnButton = UniversalCoins.Items.obsidian_coin;
			break;
		}
		if (itemOnButton == null)
			return coinField;
		if (coinField < UniversalCoins.coinValues[absoluteButton]
				|| (!inventory.get(itemCoinOutputSlot).isEmpty()
						&& inventory.get(itemCoinOutputSlot).getItem() != itemOnButton)
				|| (!inventory.get(itemCoinOutputSlot).isEmpty()
						&& inventory.get(itemCoinOutputSlot).getCount() == 64)) {
			return coinField;
		}
		if (shiftPressed) {
			if (inventory.get(itemCoinOutputSlot).isEmpty()) {
				int amount = coinField / UniversalCoins.coinValues[absoluteButton];
				if (amount >= 64) {
					coinField -= UniversalCoins.coinValues[absoluteButton] * 64;
					inventory.set(itemCoinOutputSlot, new ItemStack(itemOnButton));
					inventory.get(itemCoinOutputSlot).setCount(64);
				} else {
					coinField -= UniversalCoins.coinValues[absoluteButton] * amount;
					inventory.set(itemCoinOutputSlot, new ItemStack(itemOnButton));
					inventory.get(itemCoinOutputSlot).setCount(amount);
				}
			} else {
				int amount = Math.min(coinSum / UniversalCoins.coinValues[absoluteButton],
						inventory.get(itemCoinOutputSlot).getMaxStackSize()
								- inventory.get(itemCoinOutputSlot).getCount());
				inventory.get(itemCoinOutputSlot).grow(amount);
				coinField -= UniversalCoins.coinValues[absoluteButton] * amount;
			}
		} else {
			coinField -= UniversalCoins.coinValues[absoluteButton];
			if (inventory.get(itemCoinOutputSlot).isEmpty()) {
				inventory.set(itemCoinOutputSlot, new ItemStack(itemOnButton));
			} else {
				inventory.get(itemCoinOutputSlot).grow(1);
				;
			}
		}
		return coinField;
	}

	private void activateUserRetrieveButtons() {
		uironCoinBtnActive = false;
		ugoldCoinBtnActive = false;
		uemeraldCoinBtnActive = false;
		udiamondCoinBtnActive = false;
		uobsidianCoinBtnActive = false;
		if (userCoinSum > 0) {
			uironCoinBtnActive = inventory.get(itemCoinOutputSlot).isEmpty()
					|| (inventory.get(itemCoinOutputSlot).getItem() == UniversalCoins.Items.iron_coin
							&& inventory.get(itemCoinOutputSlot).getCount() != 64);
		}
		if (userCoinSum >= UniversalCoins.coinValues[1]) {
			ugoldCoinBtnActive = inventory.get(itemCoinOutputSlot).isEmpty()
					|| (inventory.get(itemCoinOutputSlot).getItem() == UniversalCoins.Items.gold_coin
							&& inventory.get(itemCoinOutputSlot).getCount() != 64);
		}
		if (userCoinSum >= UniversalCoins.coinValues[2]) {
			uemeraldCoinBtnActive = inventory.get(itemCoinOutputSlot).isEmpty()
					|| (inventory.get(itemCoinOutputSlot).getItem() == UniversalCoins.Items.emerald_coin
							&& inventory.get(itemCoinOutputSlot).getCount() != 64);
		}
		if (userCoinSum >= UniversalCoins.coinValues[3]) {
			udiamondCoinBtnActive = inventory.get(itemCoinOutputSlot).isEmpty()
					|| (inventory.get(itemCoinOutputSlot).getItem() == UniversalCoins.Items.diamond_coin
							&& inventory.get(itemCoinOutputSlot).getCount() != 64);
		}
		if (userCoinSum >= UniversalCoins.coinValues[4]) {
			uobsidianCoinBtnActive = inventory.get(itemCoinOutputSlot).isEmpty()
					|| (inventory.get(itemCoinOutputSlot).getItem() == UniversalCoins.Items.obsidian_coin
							&& inventory.get(itemCoinOutputSlot).getCount() != 64);
		}
	}

	public void onBuyPressed() {
		onBuyPressed(1);
	}

	public void onBuyPressed(int amount) {
		boolean useCard = false;
		// use the card if we have it
		if (!inventory.get(itemUserCardSlot).isEmpty() && getUserAccountBalance() > itemPrice * amount) {
			useCard = true;
		}
		if (!useCard && (inventory.get(itemTradeSlot).isEmpty() || userCoinSum < itemPrice * amount)) {
			buyButtonActive = false;
			return;
		}
		int totalSale = inventory.get(itemTradeSlot).getCount() * amount;
		if (!inventory.get(itemOutputSlot).isEmpty() && inventory.get(itemOutputSlot).getCount() + totalSale > inventory
				.get(itemTradeSlot).getMaxStackSize()) {
			buyButtonActive = false;
			return;
		}
		if (infiniteMode) {
			if (inventory.get(itemOutputSlot).isEmpty()) {
				inventory.set(itemOutputSlot, inventory.get(itemTradeSlot).copy());
				inventory.get(itemOutputSlot).setCount(totalSale);
				if (useCard && !inventory.get(itemUserCardSlot).isEmpty()) {
					debitUserAccount(itemPrice * amount);
				} else {
					userCoinSum -= itemPrice * amount;
				}
			} else {
				totalSale = Math.min(inventory.get(itemTradeSlot).getCount() * amount,
						inventory.get(itemTradeSlot).getMaxStackSize() - inventory.get(itemOutputSlot).getCount());
				inventory.get(itemOutputSlot).grow(totalSale);
				if (useCard && !inventory.get(itemUserCardSlot).isEmpty()) {
					debitUserAccount(itemPrice * amount);
				} else {
					userCoinSum -= itemPrice * amount;
				}
			}
			if (infiniteMode) {
				coinSum = 0;
			} else {
				if (!inventory.get(itemCardSlot).isEmpty()
						&& inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card
						&& getOwnerAccountBalance() != -1
						&& getOwnerAccountBalance() + (itemPrice * amount) < Integer.MAX_VALUE) {
					creditOwnerAccount(itemPrice * amount);
				} else {
					coinSum += itemPrice * amount;
				}
			}
		} else {
			// find matching item in inventory
			// we need to match the item, damage, and tags to make sure the
			// stacks are equal
			for (int i = itemStorageSlot1; i <= itemStorageSlot9; i++) {
				if (!inventory.get(i).isEmpty() && inventory.get(i).getItem() == inventory.get(itemTradeSlot).getItem()
						&& inventory.get(i).getItemDamage() == inventory.get(itemTradeSlot).getItemDamage()
						&& ItemStack.areItemStackTagsEqual(inventory.get(i), inventory.get(itemTradeSlot))) {
					// copy itemstack if null. We'll set the amount to 0 to
					// start.
					if (inventory.get(itemOutputSlot).isEmpty()) {
						inventory.set(itemOutputSlot, inventory.get(i).copy());
						inventory.get(itemOutputSlot).setCount(0);
					}
					int thisSale = Math.min(inventory.get(i).getCount(), totalSale);
					inventory.get(itemOutputSlot).grow(thisSale);
					inventory.get(i).shrink(thisSale);
					totalSale -= thisSale;
					if (useCard && inventory.get(itemCardSlot).isEmpty()) {
						debitUserAccount(itemPrice * thisSale / inventory.get(itemTradeSlot).getCount());
					} else {
						userCoinSum -= itemPrice * thisSale / inventory.get(itemTradeSlot).getCount();
					}
					if (infiniteMode) {
						coinSum = 0;
					} else {
						if (!inventory.get(itemCardSlot).isEmpty()
								&& inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card
								&& getOwnerAccountBalance() != -1
								&& getOwnerAccountBalance() + (itemPrice * amount) < Integer.MAX_VALUE) {
							creditOwnerAccount(itemPrice * thisSale / inventory.get(itemTradeSlot).getCount());
						} else {
							coinSum += itemPrice * thisSale / inventory.get(itemTradeSlot).getCount();
						}
					}
				}
				// cleanup empty stacks
				if (inventory.get(i).isEmpty() || inventory.get(i).getCount() == 0) {
					inventory.set(i, ItemStack.EMPTY);
				}
			}
		}
		checkSellingInventory();
		update();
	}

	public void onBuyMaxPressed() {
		boolean useCard = false;
		int amount = 0;
		if (inventory.get(itemTradeSlot).isEmpty()) {
			buyButtonActive = false;
			return;
		}
		// use the card if we have it
		if (!inventory.get(itemUserCardSlot).isEmpty() && getUserAccountBalance() > itemPrice) {
			useCard = true;
		}
		if (userCoinSum < itemPrice && !useCard) { // can't buy even one
			buyButtonActive = false;
			return;
		}
		if (inventory.get(itemOutputSlot).isEmpty()) { // empty stack
			if (inventory.get(itemTradeSlot).getMaxStackSize() * itemPrice
					/ inventory.get(itemTradeSlot).getCount() <= (useCard ? getUserAccountBalance() : userCoinSum)) {
				// buy as many as will fit in a stack
				amount = inventory.get(itemTradeSlot).getMaxStackSize() / inventory.get(itemTradeSlot).getCount();
			} else {
				// buy as many as i have coins for.
				if (useCard) {
					amount = (int) (getUserAccountBalance() > itemPrice * 64 ? 64
							: getUserAccountBalance() / itemPrice);
				} else {
					amount = userCoinSum / itemPrice;
				}
			}
		} else if (inventory.get(itemOutputSlot).getItem() == inventory.get(itemTradeSlot).getItem()
				&& inventory.get(itemOutputSlot).getItemDamage() == inventory.get(itemTradeSlot).getItemDamage()
				&& ItemStack.areItemStackTagsEqual(inventory.get(itemOutputSlot), inventory.get(itemTradeSlot))
				&& inventory.get(itemOutputSlot).getCount() < inventory.get(itemTradeSlot).getMaxStackSize()) {
			if ((inventory.get(itemOutputSlot).getMaxStackSize() - inventory.get(itemOutputSlot).getCount())
					* itemPrice <= userCoinSum) {
				// buy as much as i can fit in a stack since we have enough
				// coins
				amount = (inventory.get(itemTradeSlot).getMaxStackSize() - inventory.get(itemOutputSlot).getCount())
						/ inventory.get(itemOutputSlot).getCount();
			} else {
				if (useCard) {
					amount = (int) (getUserAccountBalance() > itemPrice * 64 ? 64
							: getUserAccountBalance() / itemPrice);
				} else {
					amount = userCoinSum / itemPrice;
				}
			}
		} else {
			buyButtonActive = false;
		}
		onBuyPressed(amount);
	}

	public void onSellPressed() {
		onSellPressed(1);
	}

	public void onSellMaxPressed() {
		onSellPressed(inventory.get(itemSellSlot).getCount());
	}

	public void onSellPressed(int amount) {
		boolean useCard = false;
		// if infinite mode, we can handle it here and skip the complicated
		// stuff
		if (infiniteMode) {
			if (!inventory.get(itemUserCardSlot).isEmpty()
					&& inventory.get(itemUserCardSlot).getItem() == UniversalCoins.Items.ender_card
					&& getUserAccountBalance() != -1 && getUserAccountBalance()
							+ (itemPrice * amount / inventory.get(itemTradeSlot).getCount()) < Integer.MAX_VALUE) {
				creditUserAccount(itemPrice * amount / inventory.get(itemTradeSlot).getCount());
			} else {
				userCoinSum += itemPrice * amount / inventory.get(itemTradeSlot).getCount();
			}
			inventory.get(itemSellSlot).shrink(amount);
			if (inventory.get(itemSellSlot).getCount() == 0) {
				inventory.set(itemSellSlot, ItemStack.EMPTY);
			}
			return;
		}
		// use the card if we have it
		if (!inventory.get(itemCardSlot).isEmpty() && getOwnerAccountBalance() > itemPrice) {
			useCard = true;
		}
		if (inventory.get(itemSellSlot).isEmpty() || coinSum < itemPrice && !useCard) {
			sellButtonActive = false;
			return;
		}
		// adjust the amount to the lesser of max the available coins will buy
		// or the amount requested
		if (useCard) {
			amount = (int) Math.min(getOwnerAccountBalance() / (itemPrice * inventory.get(itemTradeSlot).getCount()),
					amount);
		} else {
			amount = Math.min(coinSum / (itemPrice * inventory.get(itemTradeSlot).getCount()), amount);
		}
		// find empty slot or matching item in inventory
		// we need to match the item, damage, and tags to make sure the
		// stacks are equal
		for (int i = itemStorageSlot1; i <= itemStorageSlot9; i++) {
			if (!inventory.get(itemSellSlot).isEmpty()) {
				// copy itemstack if null. We'll set the amount to 0 to start.
				int thisSale = 0;
				if (!inventory.get(i).isEmpty() && inventory.get(i).getItem() == inventory.get(itemTradeSlot).getItem()
						&& inventory.get(i).getItemDamage() == inventory.get(itemTradeSlot).getItemDamage()
						&& ItemStack.areItemStackTagsEqual(inventory.get(i), inventory.get(itemTradeSlot))) {
					thisSale = Math.min(inventory.get(i).getMaxStackSize() - inventory.get(i).getCount(), amount);
					inventory.get(i).grow(thisSale);
					inventory.get(itemSellSlot).shrink(thisSale);
					amount -= thisSale;
				} else if (inventory.get(i).isEmpty()) {
					thisSale = Math.min(inventory.get(itemSellSlot).getCount(), amount);
					inventory.set(i, inventory.get(itemSellSlot).copy());
					inventory.get(i).setCount(thisSale);
					inventory.get(itemSellSlot).shrink(thisSale);
					amount -= thisSale;
				}
				if (useCard && !inventory.get(itemCardSlot).isEmpty()) {
					debitOwnerAccount(itemPrice * thisSale / inventory.get(itemTradeSlot).getCount());
				} else {
					coinSum -= itemPrice * thisSale / inventory.get(itemTradeSlot).getCount();
				}
				if (!inventory.get(itemUserCardSlot).isEmpty()
						&& inventory.get(itemUserCardSlot).getItem() instanceof ItemEnderCard
						&& getUserAccountBalance() != -1 && getUserAccountBalance() + (itemPrice * thisSale
								/ inventory.get(itemTradeSlot).getCount()) < Integer.MAX_VALUE) {
					creditUserAccount(itemPrice * thisSale / inventory.get(itemTradeSlot).getCount());
				} else {
					userCoinSum += itemPrice * thisSale / inventory.get(itemTradeSlot).getCount();
				}
				// cleanup empty stacks
				if (inventory.get(itemSellSlot).isEmpty() || inventory.get(itemSellSlot).getCount() == 0) {
					inventory.set(itemSellSlot, ItemStack.EMPTY);
				}
				if (amount == 0) {
					updateCoinsForPurchase(); // we bought stuff. Make sure we
												// have coins left.
					return; // we are done here. exit the loop.
				}
			}
		}
		update();
	}

	public void onModeButtonPressed() {
		sellMode ^= true;
		updateSigns();
	}

	public void checkSellingInventory() {
		for (int i = itemStorageSlot1; i <= itemStorageSlot9; i++) {
			if (!inventory.get(i).isEmpty() && !inventory.get(itemTradeSlot).isEmpty()
					&& inventory.get(i).getItem() == inventory.get(itemTradeSlot).getItem()) {
				if (ooStockWarning) {
					this.ooStockWarning = false;
					updateSigns();
				}
				return;
			}
		}
		if (!ooStockWarning) {
			this.ooStockWarning = true; // if we reach this point, we are OOS.
			updateSigns();
		}
	}

	public boolean hasInventorySpace() {
		if (!inventory.get(itemTradeSlot).isEmpty()) {
			for (int i = itemStorageSlot1; i <= itemStorageSlot9; i++) {
				if (inventory.get(i).isEmpty() || (inventory.get(i).getItem() == inventory.get(itemTradeSlot).getItem()
						&& inventory.get(i).getCount() < inventory.get(i).getMaxStackSize())) {
					if (inventoryFullWarning) {
						this.inventoryFullWarning = false;
						updateSigns();
					}
					return true;
				}
			}
			if (!inventoryFullWarning) {
				this.inventoryFullWarning = true; // if we reach this point, we
													// have no space left.
				updateSigns();
			}
			return false;
		} else
			return true;
	}

	public void updateCoinsForPurchase() {
		if (coinSum >= itemPrice || (!inventory.get(itemCardSlot).isEmpty() && getOwnerAccountBalance() >= itemPrice)) {
			this.ooCoinsWarning = false;
			updateSigns();
		} else {
			this.ooCoinsWarning = true;
			updateSigns();
		}
	}

	public ItemStack getSellItem() {
		return inventory.get(itemTradeSlot);
	}

	public void setSellItem(ItemStack stack) {
		inventory.set(itemTradeSlot, stack);
	}

	@Override
	public int getSizeInventory() {
		return inventory.size();
	}

	@Override
	public ItemStack getStackInSlot(int index) {
		return inventory.get(index);
	}

	@Override
	public ItemStack decrStackSize(int slot, int size) {
		ItemStack stack = getStackInSlot(slot);
		if (size < stack.getCount()) {
			stack = stack.splitStack(size);
		} else {
			setInventorySlotContents(slot, ItemStack.EMPTY);
		}
		if (slot < itemStorageSlot9) { // update inventory status
			checkSellingInventory();
			hasInventorySpace();
		}
		return stack;
	}

	// @Override
	public ItemStack getStackInSlotOnClosing(int i) {
		ItemStack itemstack = this.inventory.get(i);
		inventory.remove(i);
		inUse = false;
		return itemstack;
	}

	@Override
	public void setInventorySlotContents(int slot, ItemStack stack) {
		inventory.set(slot, stack);
		int coinValue = CoinUtils.getCoinValue(stack);

		int depositAmount = 0;
		if (slot == itemCoinInputSlot && !stack.isEmpty()) {
			depositAmount = Math.min(stack.getCount(), (Integer.MAX_VALUE - coinSum) / coinValue);
			if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound()
					&& inventory.get(itemCardSlot).getItem() == UniversalCoins.Items.ender_card
					&& getOwnerAccountBalance() != -1
					&& getOwnerAccountBalance() + (depositAmount * coinValue) < Integer.MAX_VALUE) {
				creditOwnerAccount(depositAmount * coinValue);
			} else {
				coinSum += depositAmount * coinValue;
			}
			updateCoinsForPurchase();
		}
		if (slot == itemUserCoinInputSlot && !stack.isEmpty()) {
			depositAmount = Math.min(stack.getCount(), (Integer.MAX_VALUE - userCoinSum) / coinValue);
			if (!inventory.get(itemUserCardSlot).isEmpty() && inventory.get(itemUserCardSlot).hasTagCompound()
					&& inventory.get(itemUserCardSlot).getItem() == UniversalCoins.Items.ender_card
					&& getUserAccountBalance() != -1
					&& getUserAccountBalance() + (depositAmount * coinValue) < Integer.MAX_VALUE) {
				creditUserAccount(depositAmount * coinValue);
			} else {
				userCoinSum += depositAmount * coinValue;
			}
		}
		inventory.get(slot).shrink(depositAmount);
		if (inventory.get(slot).getCount() == 0) {
			inventory.set(slot, ItemStack.EMPTY);
		}
		if (slot == itemCardSlot) {
			updateCoinsForPurchase();
		}
		if (slot == itemUserCardSlot && !stack.isEmpty()
				&& inventory.get(itemUserCardSlot).getItem() instanceof ItemEnderCard && getUserAccountBalance() != -1
				&& getUserAccountBalance() + userCoinSum < Integer.MAX_VALUE) {
			creditUserAccount(userCoinSum);
			userCoinSum = 0;
		}
		checkSellingInventory(); // update inventory status
		hasInventorySpace();
		update();
	}

	public String getName() {
		return UniversalCoins.Blocks.vendor_block.getLocalizedName();
	}

	@Override
	public boolean hasCustomName() {
		return false;
	}

	@Override
	public int getInventoryStackLimit() {
		return 64;
	}

	@Override
	public boolean isItemValidForSlot(int slot, ItemStack stack) {
		if (slot == itemTradeSlot) {
			inventory.set(itemTradeSlot, stack.copy());
			return false;
		} else
			return true;
	}

	public void sendServerUpdateMessage() {
		UniversalCoins.snw.sendToServer(
				new UCVendorServerMessage(pos.getX(), pos.getY(), pos.getZ(), itemPrice, blockOwner, infiniteMode));
	}

	public void readFromNBT(NBTTagCompound tagCompound) {
		super.readFromNBT(tagCompound);
		this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
		ItemStackHelper.loadAllItems(tagCompound, this.inventory);
		try {
			coinSum = tagCompound.getInteger("CoinSum");
		} catch (Throwable ex2) {
			coinSum = 0;
		}
		try {
			userCoinSum = tagCompound.getInteger("UserCoinSum");
		} catch (Throwable ex2) {
			userCoinSum = 0;
		}
		try {
			itemPrice = tagCompound.getInteger("ItemPrice");
		} catch (Throwable ex2) {
			itemPrice = 0;
		}
		try {
			infiniteMode = tagCompound.getBoolean("Infinite");
		} catch (Throwable ex2) {
			infiniteMode = false;
		}
		try {
			sellMode = tagCompound.getBoolean("Mode");
		} catch (Throwable ex2) {
			sellMode = false;
		}
		try {
			ooStockWarning = tagCompound.getBoolean("OutOfStock");
		} catch (Throwable ex2) {
			ooStockWarning = false;
		}
		try {
			ooCoinsWarning = tagCompound.getBoolean("OutOfCoins");
		} catch (Throwable ex2) {
			ooCoinsWarning = false;
		}
		try {
			inventoryFullWarning = tagCompound.getBoolean("InventoryFull");
		} catch (Throwable ex2) {
			inventoryFullWarning = false;
		}
		try {
			buyButtonActive = tagCompound.getBoolean("BuyButtonActive");
		} catch (Throwable ex2) {
			buyButtonActive = false;
		}
		try {
			sellButtonActive = tagCompound.getBoolean("SellButtonActive");
		} catch (Throwable ex2) {
			sellButtonActive = false;
		}
		try {
			ironCoinBtnActive = tagCompound.getBoolean("ironCoinBtnActive");
		} catch (Throwable ex2) {
			ironCoinBtnActive = false;
		}
		try {
			goldCoinBtnActive = tagCompound.getBoolean("goldCoinBtnActive");
		} catch (Throwable ex2) {
			goldCoinBtnActive = false;
		}
		try {
			emeraldCoinBtnActive = tagCompound.getBoolean("emeraldCoinBtnActive");
		} catch (Throwable ex2) {
			emeraldCoinBtnActive = false;
		}
		try {
			diamondCoinBtnActive = tagCompound.getBoolean("diamondCoinBtnActive");
		} catch (Throwable ex2) {
			diamondCoinBtnActive = false;
		}
		try {
			obsidianCoinBtnActive = tagCompound.getBoolean("obsidianCoinBtnActive");
		} catch (Throwable ex2) {
			obsidianCoinBtnActive = false;
		}
		try {
			uironCoinBtnActive = tagCompound.getBoolean("uironCoinBtnActive");
		} catch (Throwable ex2) {
			uironCoinBtnActive = false;
		}
		try {
			ugoldCoinBtnActive = tagCompound.getBoolean("ugoldCoinBtnActive");
		} catch (Throwable ex2) {
			ugoldCoinBtnActive = false;
		}
		try {
			uemeraldCoinBtnActive = tagCompound.getBoolean("uemeraldCoinBtnActive");
		} catch (Throwable ex2) {
			uemeraldCoinBtnActive = false;
		}
		try {
			udiamondCoinBtnActive = tagCompound.getBoolean("udiamondCoinBtnActive");
		} catch (Throwable ex2) {
			udiamondCoinBtnActive = false;
		}
		try {
			uobsidianCoinBtnActive = tagCompound.getBoolean("uobsidianCoinBtnActive");
		} catch (Throwable ex2) {
			uobsidianCoinBtnActive = false;
		}
		try {
			textColor = tagCompound.getInteger("TextColor");
		} catch (Throwable ex2) {
			textColor = 0x0;
		}
		try {
			remoteX = tagCompound.getInteger("remoteX");
		} catch (Throwable ex2) {
			remoteX = 0;
		}
		try {
			remoteY = tagCompound.getInteger("remoteY");
		} catch (Throwable ex2) {
			remoteY = 0;
		}
		try {
			remoteZ = tagCompound.getInteger("remoteZ");
		} catch (Throwable ex2) {
			remoteZ = 0;
		}
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tagCompound) {
		super.writeToNBT(tagCompound);
		ItemStackHelper.saveAllItems(tagCompound, this.inventory);
		tagCompound.setInteger("CoinSum", coinSum);
		tagCompound.setInteger("UserCoinSum", userCoinSum);
		tagCompound.setInteger("ItemPrice", itemPrice);
		tagCompound.setBoolean("Infinite", infiniteMode);
		tagCompound.setBoolean("Mode", sellMode);
		tagCompound.setBoolean("OutOfStock", ooStockWarning);
		tagCompound.setBoolean("OutOfCoins", ooCoinsWarning);
		tagCompound.setBoolean("InventoryFull", inventoryFullWarning);
		tagCompound.setBoolean("BuyButtonActive", buyButtonActive);
		tagCompound.setBoolean("SellButtonActive", sellButtonActive);
		tagCompound.setBoolean("ironCoinBtnActive", ironCoinBtnActive);
		tagCompound.setBoolean("goldCoinBtnActive", goldCoinBtnActive);
		tagCompound.setBoolean("emeraldCoinBtnActive", emeraldCoinBtnActive);
		tagCompound.setBoolean("diamondCoinBtnActive", diamondCoinBtnActive);
		tagCompound.setBoolean("obsidianCoinBtnActive", obsidianCoinBtnActive);
		tagCompound.setBoolean("uironCoinBtnActive", uironCoinBtnActive);
		tagCompound.setBoolean("ugoldCoinBtnActive", ugoldCoinBtnActive);
		tagCompound.setBoolean("uemeraldCoinBtnActive", uemeraldCoinBtnActive);
		tagCompound.setBoolean("udiamondCoinBtnActive", udiamondCoinBtnActive);
		tagCompound.setBoolean("uobsidianCoinBtnActive", uobsidianCoinBtnActive);
		tagCompound.setInteger("TextColor", textColor);
		tagCompound.setInteger("remoteX", remoteX);
		tagCompound.setInteger("remoteY", remoteY);
		tagCompound.setInteger("remoteZ", remoteZ);
		return tagCompound;
	}

	public void updateSigns() {
	}

	public void setRemoteStorage(int[] storageLocation) {
		remoteX = storageLocation[0];
		remoteY = storageLocation[1];
		remoteZ = storageLocation[2];
	}

	public void checkRemoteStorage() {
		if (remoteX != 0 && remoteY != 0 && remoteZ != 0 && !inventory.get(itemTradeSlot).isEmpty()) {
			for (int i = itemStorageSlot1; i <= itemStorageSlot9; i++) {
				if (inventory.get(i).isEmpty()) {
					loadRemoteChunk(remoteX, remoteY, remoteZ);
					TileEntity te = world.getTileEntity(new BlockPos(remoteX, remoteY, remoteZ));
					if (te != null && te instanceof TileEntityChest) {
						TileEntityChest chest = (TileEntityChest) te;
						for (int j = 0; j < chest.getSizeInventory(); j++) {
							if (inventory.get(i).isEmpty() && !chest.getStackInSlot(j).isEmpty()
									&& chest.getStackInSlot(j).getItem() == inventory.get(itemTradeSlot).getItem()) {
								inventory.set(i, chest.getStackInSlot(j));
								chest.setInventorySlotContents(j, ItemStack.EMPTY);
								checkSellingInventory();
							}
						}
					}
				}
			}
		}
	}

	public long getUserAccountBalance() {
		if (!inventory.get(itemUserCardSlot).isEmpty() && inventory.get(itemUserCardSlot).hasTagCompound()
				&& !world.isRemote) {
			String accountNumber = inventory.get(itemUserCardSlot).getTagCompound().getString("Account");
			return UniversalAccounts.getInstance().getAccountBalance(accountNumber);
		}
		return -1;
	}

	public void debitUserAccount(int amount) {
		if (!inventory.get(itemUserCardSlot).isEmpty() && inventory.get(itemUserCardSlot).hasTagCompound()
				&& !world.isRemote) {
			String accountNumber = inventory.get(itemUserCardSlot).getTagCompound().getString("Account");
			UniversalAccounts.getInstance().debitAccount(accountNumber, amount, false);
		}
	}

	public void creditUserAccount(int amount) {
		if (!inventory.get(itemUserCardSlot).isEmpty() && inventory.get(itemUserCardSlot).hasTagCompound()
				&& !world.isRemote) {
			String accountNumber = inventory.get(itemUserCardSlot).getTagCompound().getString("Account");
			UniversalAccounts.getInstance().creditAccount(accountNumber, amount, false);
		}
	}

	public long getOwnerAccountBalance() {
		if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound() && !world.isRemote) {
			String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			return UniversalAccounts.getInstance().getAccountBalance(accountNumber);
		}
		return -1;
	}

	public void debitOwnerAccount(int amount) {
		if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound() && !world.isRemote) {
			String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			UniversalAccounts.getInstance().debitAccount(accountNumber, amount, false);
		}
	}

	public void creditOwnerAccount(int amount) {
		if (!inventory.get(itemCardSlot).isEmpty() && inventory.get(itemCardSlot).hasTagCompound() && !world.isRemote) {
			String accountNumber = inventory.get(itemCardSlot).getTagCompound().getString("Account");
			UniversalAccounts.getInstance().creditAccount(accountNumber, amount, false);
		}
	}

	private void loadRemoteChunk(int x, int y, int z) {
		Chunk ch = world.getChunkFromChunkCoords(x, y);
		world.getChunkProvider().provideChunk(ch.x, ch.z);
	}

	public void onButtonPressed(int buttonId, boolean shiftPressed) {
		if (buttonId == VendorGUI.idModeButton) {
			onModeButtonPressed();
		} else if (buttonId >= VendorGUI.idIronCoinBtn && buttonId <= VendorGUI.idObsidianCoinBtn) {
			onRetrieveButtonsPressed(buttonId, shiftPressed);
		} else if (buttonId == VendorGUI.idtcmButton) {
			if (textColor > 0)
				textColor--;
		} else if (buttonId == VendorGUI.idtcpButton) {
			if (textColor < 15)
				textColor++;
		} else if (buttonId == VendorBuyGUI.idSellButton) {
			if (shiftPressed) {
				onSellMaxPressed();
			} else {
				onSellPressed();
			}
		} else if (buttonId == VendorSellGUI.idBuyButton) {
			if (shiftPressed) {
				onBuyMaxPressed();
			} else {
				onBuyPressed();
			}
		} else if (buttonId >= VendorBuyGUI.idIronCoinBtn && buttonId <= VendorBuyGUI.idObsidianCoinBtn) {
			onRetrieveButtonsPressed(buttonId, shiftPressed);
		}
		update();
	}

	@Override
	public ITextComponent getDisplayName() {
		return new TextComponentString(UniversalCoins.Blocks.vendor_block.getLocalizedName());
	}

	@Override
	public void openInventory(EntityPlayer player) {
	}

	@Override
	public void closeInventory(EntityPlayer player) {
	}

	@Override
	public int getField(int id) {
		return 0;
	}

	@Override
	public void setField(int id, int value) {

	}

	@Override
	public int getFieldCount() {
		return 0;
	}

	@Override
	public void clear() {

	}

	@Override
	public boolean isEmpty() {
		return false;
	}

	@Override
	public ItemStack removeStackFromSlot(int index) {
		return inventory.get(index);
	}

	public boolean isUsableByPlayer(EntityPlayer player) {
		if (this.world.getTileEntity(this.pos) != this || player == null) {
			return false;
		} else {
			return player.getDistanceSq((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D,
					(double) this.pos.getZ() + 0.5D) <= 64.0D;
		}
	}
} public class TileVendorBlock extends TileVendor {

	String signText[] = { "", "", "", "" };

	public void updateSigns() {

		if (!inventory.get(itemTradeSlot).isEmpty()) {
			signText[0] = sellMode ? "&" + Integer.toHexString(textColor) + "Selling"
					: "&" + Integer.toHexString(textColor) + "Buying";
			// add out of stock notification if not infinite and no stock found
			if (!infiniteMode && sellMode && ooStockWarning) {
				signText[0] = "&" + Integer.toHexString(textColor) + (I18n.translateToLocal("sign.warning.stock"));
			}
			// add out of coins notification if buying and no funds available
			if (!sellMode && ooCoinsWarning && !infiniteMode) {
				signText[0] = "&" + Integer.toHexString(textColor) + (I18n.translateToLocal("sign.warning.coins"));
			}
			// add inventory full notification
			if (!sellMode && inventoryFullWarning) {
				signText[0] = "&" + Integer.toHexString(textColor)
						+ (I18n.translateToLocal("sign.warning.inventoryfull"));
			}
			if (inventory.get(itemTradeSlot).getCount() > 1) {
				signText[1] = "&" + Integer.toHexString(textColor) + inventory.get(itemTradeSlot).getCount() + " "
						+ inventory.get(itemTradeSlot).getDisplayName();
			} else {
				signText[1] = "&" + Integer.toHexString(textColor) + inventory.get(itemTradeSlot).getDisplayName();
			}
			// if (inventory.get(itemTradeSlot).isItemEnchanted()) {
			// signText[2] = "&" + Integer.toHexString(textColor);
			// NBTTagList tagList =
			// inventory.get(itemTradeSlot).getEnchantmentTagList();
			// for (int i = 0; i < tagList.tagCount(); i++) {
			// NBTTagCompound enchant = ((NBTTagList)
			// tagList).getCompoundTagAt(i);
			// signText[2] =
			// signText[2].concat(Enchantment.enchantmentsBookList[enchant.getInteger("id")]
			// .getTranslatedName(enchant.getInteger("lvl")) + ", ");
			// }
			// } else
			// signText[2] = "";
			if (inventory.get(itemTradeSlot).getItem() == UniversalCoins.Items.uc_package) {
				signText[2] = "&" + Integer.toHexString(textColor);
				if (inventory.get(itemTradeSlot).getTagCompound() != null) {
					NBTTagList tagList = inventory.get(itemTradeSlot).getTagCompound().getTagList("Inventory",
							Constants.NBT.TAG_COMPOUND);
					for (int i = 0; i < tagList.tagCount(); i++) {
						NBTTagCompound tag = (NBTTagCompound) tagList.getCompoundTagAt(i);
						int itemCount = new ItemStack(tag).getCount();
						String itemName = new ItemStack(tag).getDisplayName();
						signText[2] += itemCount + ":" + itemName + " ";
					}
				}
			}
			signText[3] = "&" + Integer.toHexString(textColor) + "Price: " + itemPrice;

			// find and update all signs
			TileEntity te;
			te = world.getTileEntity(new BlockPos(pos.getX() + 1, pos.getY() - 1, pos.getZ()));
			if (te != null && te instanceof TileUCSign) {
				TileUCSign tesign = (TileUCSign) te;
				for (int i = 0; i < 4; i++) {
					tesign.signText[i] = new TextComponentString(this.signText[i]);
				}
				tesign.updateSign();
				tesign.markDirty();
			}
			te = world.getTileEntity(new BlockPos(pos.getX() - 1, pos.getY() - 1, pos.getZ()));
			if (te != null && te instanceof TileUCSign) {
				TileUCSign tesign = (TileUCSign) te;
				for (int i = 0; i < 4; i++) {
					tesign.signText[i] = new TextComponentString(this.signText[i]);
				}
				tesign.updateSign();
				tesign.markDirty();
			}
			te = world.getTileEntity(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ() - 1));
			if (te != null && te instanceof TileUCSign) {
				TileUCSign tesign = (TileUCSign) te;
				for (int i = 0; i < 4; i++) {
					tesign.signText[i] = new TextComponentString(this.signText[i]);
				}
				tesign.updateSign();
				tesign.markDirty();
			}
			te = world.getTileEntity(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ() + 1));
			if (te != null && te instanceof TileUCSign) {
				TileUCSign tesign = (TileUCSign) te;
				for (int i = 0; i < 4; i++) {
					tesign.signText[i] = new TextComponentString(this.signText[i]);
				}
				tesign.updateSign();
				tesign.markDirty();
			}
		}
	}
} public class TileVendorFrame extends TileVendor {

	String signText[] = { "", "", "", "" };

	@Override
	public String getName() {
		return I18n.translateToLocal("tile.universalcoins.vendor_frame.name");
	}

	public void updateSigns() {

		if (!inventory.get(itemTradeSlot).isEmpty()) {

			signText[0] = sellMode ? "&" + Integer.toHexString(textColor) + "Selling"
					: "&" + Integer.toHexString(textColor) + "Buying";
			// add out of stock notification if not infinite and no stock found
			if (!infiniteMode && sellMode && ooStockWarning) {
				signText[0] = "&" + Integer.toHexString(textColor) + (I18n.translateToLocal("sign.warning.stock"));
			}
			// add out of coins notification if buying and no funds available
			if (!sellMode && ooCoinsWarning && !infiniteMode) {
				signText[0] = "&" + Integer.toHexString(textColor) + (I18n.translateToLocal("sign.warning.coins"));
			}
			// add inventory full notification
			if (!sellMode && inventoryFullWarning) {
				signText[0] = "&" + Integer.toHexString(textColor)
						+ (I18n.translateToLocal("sign.warning.inventoryfull"));
			}
			if (inventory.get(itemTradeSlot).getCount() > 1) {
				signText[1] = "&" + Integer.toHexString(textColor) + inventory.get(itemTradeSlot).getCount() + " "
						+ inventory.get(itemTradeSlot).getDisplayName();
			} else {
				signText[1] = "&" + Integer.toHexString(textColor) + inventory.get(itemTradeSlot).getDisplayName();
			}
			if (inventory.get(itemTradeSlot).isItemEnchanted()) {
				signText[2] = "&" + Integer.toHexString(textColor);
				NBTTagList tagList = inventory.get(itemTradeSlot).getEnchantmentTagList();
				for (int i = 0; i < tagList.tagCount(); i++) {
					((NBTTagList) tagList).getCompoundTagAt(i);
				}
			} else
				signText[2] = "";
			if (inventory.get(itemTradeSlot).getItem() == UniversalCoins.Items.uc_package) {
				if (inventory.get(itemTradeSlot).getTagCompound() != null) {
					signText[2] = "&" + Integer.toHexString(textColor);
					NBTTagList tagList = inventory.get(itemTradeSlot).getTagCompound().getTagList("Inventory",
							Constants.NBT.TAG_COMPOUND);
					for (int i = 0; i < tagList.tagCount(); i++) {
						NBTTagCompound tag = (NBTTagCompound) tagList.getCompoundTagAt(i);
						int itemCount = new ItemStack(tag).getCount();
						String itemName = new ItemStack(tag).getDisplayName();
						signText[2] += itemCount + ":" + itemName + " ";
					}
				}
			}
			signText[3] = "&" + Integer.toHexString(textColor) + "Price: " + itemPrice;

			// find and update all signs
			TileEntity te;
			te = super.world.getTileEntity(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ()));
			if (te != null && te instanceof TileUCSign) {
				TileUCSign tesign = (TileUCSign) te;
				for (int i = 0; i < 4; i++) {
					tesign.signText[i] = new TextComponentString(this.signText[i]);
				}
				tesign.updateSign();
				tesign.markDirty();
			}
			te = super.world.getTileEntity(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()));
			if (te != null && te instanceof TileUCSign) {
				TileUCSign tesign = (TileUCSign) te;
				for (int i = 0; i < 4; i++) {
					tesign.signText[i] = new TextComponentString(this.signText[i]);
				}
				tesign.updateSign();
				tesign.markDirty();
			}
		}
	}
} public class UCItemPricer {

	private static final UCItemPricer instance = new UCItemPricer();

	private static Map<String, Integer> ucPriceMap = new HashMap<String, Integer>(0);
	private static String configPath = FMLInjectionData.data()[6] + "/config/universalcoins/";
	private Random random = new Random();

	public static UCItemPricer getInstance() {
		return instance;
	}

	private UCItemPricer() {

	}

	public void loadConfigs() {
		if (!new File(configPath).exists()) {
			// FMLLog.log.info("Universal Coins: Loading default prices");
			updateItems();
			updateEnchantments();
			updatePotions();
			updateOreDictionary();
			try {
				loadDefaults();
			} catch (IOException e) {
				FMLLog.log.warn("Universal Coins: Failed to load default configs");
				e.printStackTrace();
			}
			priceCoins();
			priceCraftedItems();
			priceSmeltedItems();
			writePriceLists();
		} else {
			try {
				loadPricelists();
			} catch (IOException e) {
				FMLLog.log.warn("Universal Coins: Failed to load config files");
				e.printStackTrace();
			}
		}
	}

	private void loadDefaults() throws IOException {
		String[] configList = { "pricelists/minecraft.csv" };
		InputStream priceResource;
		// load those files into hashmap(ucPriceMap)
		for (int i = 0; i < configList.length; i++) {
			priceResource = UCItemPricer.class.getResourceAsStream(configList[i]);
			if (priceResource == null) {
				return;
			}
			String priceString = convertStreamToString(priceResource);
			processDefaultConfigs(priceString);
		}
	}

	private String convertStreamToString(java.io.InputStream is) {
		// Thanks to Pavel Repin on StackOverflow.
		java.util.Scanner scanner = new java.util.Scanner(is);
		java.util.Scanner s = scanner.useDelimiter("\\A");
		String result = s.hasNext() ? s.next() : "";
		scanner.close();
		return result;
	}

	private void processDefaultConfigs(String priceString) {
		StringTokenizer tokenizer = new StringTokenizer(priceString, "\n\r", false);
		while (tokenizer.hasMoreElements()) {
			String token = tokenizer.nextToken();
			String[] tempData = token.split("=");
			if (ucPriceMap.get(tempData[0]) != null && tempData.length == 2) {
				ucPriceMap.put(tempData[0], Integer.valueOf(tempData[1]));
			}
		}
	}

	private void loadPricelists() throws IOException {
		// search config file folder for files
		File folder = new File(configPath);
		File[] configList = folder.listFiles();
		// load those files into hashmap(UCPriceMap)
		for (int i = 0; i < configList.length; i++) {
			if (configList[i].isFile()) {
				// FMLLog.log.info("Universal Coins: Loading Pricelist: " + configList[i]);
				BufferedReader br = new BufferedReader(new FileReader(configList[i]));
				String tempString = "";
				while ((tempString = br.readLine()) != null) {
					if (tempString.startsWith("//") || tempString.startsWith("#")) {
						continue; // we have a comment. skip it
					}
					String[] tempData = tempString.split("=");
					if (tempData.length < 2) {
						// something is wrong with this line
						FMLLog.log.warn("Universal Coins: ERROR: line containing " + tempString + " in "
								+ configList[i].getName() + " is invalid");
						continue;
					}
					int itemPrice = -1;
					try {
						itemPrice = Integer.valueOf(tempData[1]);
					} catch (NumberFormatException e) {
						FMLLog.log.warn("Universal Coins: ERROR: line containing " + tempString + " in "
								+ configList[i].getName() + " is invalid");
					}
					ucPriceMap.put(tempData[0], itemPrice);
				}
				br.close();
			}
		}
	}

	private boolean writePriceLists() {
		// writing pricelists takes a while so we start a thread and let it work
		// in the background.
		try {
			priceListWriter();
		} catch (IOException e) {
			FMLLog.log.warn("UniversalCoins: Failed to create config file");
			e.printStackTrace();
			return false;
		}
		return true;
	}

	private void priceListWriter() throws IOException {
		System.currentTimeMillis();

		Set<Entry<String, Integer>> set = ucPriceMap.entrySet();
		List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);
		Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
			public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
				return o2.getKey().compareTo(o1.getKey());
			}
		});

		Path pathToFile = Paths.get(configPath + list.get(0).getKey().split("\\W", 2)[0]);
		Files.createDirectories(pathToFile.getParent());

		File csvFile = new File(configPath + list.get(0).getKey().split("\\W", 2)[0] + ".csv");
		// FMLLog.log.info("csvFile: " + csvFile);
		if (csvFile.exists()) {
			csvFile.delete();
			csvFile.createNewFile();
		}
		BufferedWriter out = new BufferedWriter(new FileWriter(csvFile));
		String previousModName = list.get(0).getKey().split("\\W", 2)[0];
		for (Entry<String, Integer> entry : list) {
			String modName = entry.getKey().split("\\W", 2)[0];
			// FMLLog.log.info("working on : " + entry.getKey());
			if (!modName.matches(previousModName)) {
				// FMLLog.log.info("New mod name");
				previousModName = modName;
				out.flush();
				out.close();
				// move to next file
				csvFile = new File(configPath + entry.getKey().split("\\W", 2)[0] + ".csv");
				if (csvFile.exists()) {
					csvFile.delete();
					csvFile.createNewFile();
				}
				out = new BufferedWriter(new FileWriter(csvFile));
			}
			int price = ucPriceMap.get(entry.getKey());
			out.write(entry.getKey() + "=" + price);
			out.newLine();
		}
		out.flush();
		out.close();
		System.currentTimeMillis();
	}

	public int getItemPrice(ItemStack itemStack) {
		// FMLLog.log.info("UC: in getItemPrice");
		if (itemStack.isEmpty()) {
			return -1;
		}
		if (itemStack.getItemDamage() == 32767) {
			itemStack.setItemDamage(0);
		}
		int itemPrice = -1;
		String itemName = null;
		try {
			itemStack.getItemDamage();
			if (itemStack.isItemStackDamageable()) {
			}
			if (itemStack.isItemStackDamageable()) {
				itemName = itemStack.getItem().getRegistryName() + ".0";
			} else {
				itemName = itemStack.getItem().getRegistryName() + "." + itemStack.getItemDamage();
			}
		} catch (Exception e) {
			FMLLog.log.warn("getItemPrice: Error item name for " + itemStack);
			return -1;
		}
		if (ucPriceMap.get(itemName) != null) {
			itemPrice = ucPriceMap.get(itemName);
			// FMLLog.log.info("getItemPrice: " + itemName + " price = " + itemPrice);
		}
		// lookup item in oreDictionary if not priced
		if (itemPrice == -1) {
			int[] id = OreDictionary.getOreIDs(itemStack);
			if (id.length > 0) {
				NonNullList<ItemStack> oreStacks = OreDictionary.getOres(OreDictionary.getOreName(id[0]));
				for (ItemStack oreStack : oreStacks) {
					itemName = oreStack.getItem().getRegistryName().toString();
					if (ucPriceMap.get(itemName + ".0") != null) {
						itemPrice = ucPriceMap.get(itemName + ".0");
					}
				}
			}
		}
		// check for enchantments/potions last so we can cancel if it's not
		// priced
		if (itemStack.hasTagCompound()) {
			NBTTagCompound tagCompound = itemStack.getTagCompound();
			String potionName = tagCompound.getString("Potion");
			// FMLLog.log.info("getItemPrice: Item has potion: " + potionName);
			// FMLLog.log.info("getItemPrice: Custom effects: " +
			// tagCompound.hasKey("CustomPotionEffects"));
			if (potionName != "" && !tagCompound.hasKey("CustomPotionEffects")) {
				if (ucPriceMap.get(potionName) != null) {
					int potionPrice = ucPriceMap.get(potionName);
					if (potionPrice == -1) {
						return -1;
					}
					itemPrice += potionPrice;
				} else {
					itemPrice = -1;
				}
			}
			if (hasEnchantment(itemStack)) {
				// FMLLog.log.info("getItemPrice: Item has enchantment");
				ArrayList<String> enchantments = getEnchantmentList(itemStack);
				for (String enchant : enchantments) {
					ResourceLocation enchantRL = getEnchantmentByName(enchant);
					// FMLLog.log.info("getItemPrice: Found enchantment: " + enchant);
					if (enchantRL != null
							&& ucPriceMap.get(enchantRL + enchant.substring(enchant.length() - 2)) != null) {

						int enchantPrice = ucPriceMap.get(enchantRL + enchant.substring(enchant.length() - 2));
						if (enchantPrice == -1) {
							return -1;
						}
						itemPrice += enchantPrice;
					} else {
						return -1;
					}

				}
			}
		}
		return itemPrice;
	}

	public boolean setItemPrice(ItemStack itemStack, int price) {
		if (itemStack == null || price <= 0 || hasEnchantment(itemStack) || hasPotion(itemStack)) {
			// FMLLog.log.info("UC: Can't price this!");
			return false;
		}
		int itemStackDamage = itemStack.getItemDamage();
		if (itemStack.isItemStackDamageable()) {
			// override for damaged items
			itemStackDamage = 0;
		}
		String itemName = itemStack.getItem().getRegistryName() + "." + itemStackDamage;
		// FMLLog.log.info("UC: setItemPrice: " + itemName + " " + price);
		ucPriceMap.put(itemName, price);
		return true;
	}

	public void updatePriceLists() {
		// delete old configs
		File folder = new File(configPath);
		// cleanup
		if (folder.exists()) {
			File[] files = folder.listFiles();
			if (null != files) {
				for (int i = 0; i < files.length; i++) {
					files[i].delete();
				}
			}
		}
		updateItems();
		updateOreDictionary();
		updatePotions();
		updateEnchantments();
		priceCoins();
		priceCraftedItems();
		priceSmeltedItems();
		// write new configs
		writePriceLists();
	}

	public void savePriceLists() {
		// delete old configs
		File folder = new File(configPath);
		// cleanup
		if (folder.exists()) {
			File[] files = folder.listFiles();
			if (null != files) {
				for (int i = 0; i < files.length; i++) {
					files[i].delete();
				}
			}
		}
		// write new configs
		writePriceLists();
	}

	public boolean resetDefaults() {
		try {
			loadDefaults();
			return true;
		} catch (IOException e) {
			return false;
		}
	}

	public ItemStack getRandomPricedStack() {
		List<String> keys = new ArrayList<String>(ucPriceMap.keySet());
		ItemStack stack = null;
		while (stack == null) {
			String keyName = keys.get(random.nextInt(keys.size())).toString();
			int price = 0;
			if (ucPriceMap.get(keyName) != null) {
				price = ucPriceMap.get(keyName);
			}
			if (price > 0) {
				// TODO update potion handling
				if (keyName.contains("potion") || keyName.contains("splash_potion")
						|| keyName.contains("lingering_potion")) {
					String[] splitKeyName = keyName.split("\\W", 2);
					Item potionItem = Item.REGISTRY.getObject(new ResourceLocation(splitKeyName[0]));
					if (potionItem != null) {
						stack = new ItemStack(potionItem, 1);
						PotionUtils.addPotionToItemStack(stack, PotionType.getPotionTypeForName(splitKeyName[1]));
					}
				}
				// oredictionary entries do not include damage value
				// we need to check for this
				if (!Character.isDigit(keyName.charAt(keyName.length() - 1))) {
					List<ItemStack> test = OreDictionary.getOres(keyName);
					for (int j = 0; j < test.size(); j++) {
						ItemStack oreDictionaryStack = (ItemStack) test.get(j);
						int subItemValue = getItemPrice(oreDictionaryStack);
						if (subItemValue > 0) {
							return oreDictionaryStack;
						}
					}
				} else {
					// split string into item name and damage
					String itemName = keyName.substring(0, keyName.length() - 2);
					int itemDamage = Integer.valueOf(keyName.substring(keyName.length() - 1));
					Item item = (Item) Item.REGISTRY.getObject(new ResourceLocation(itemName));
					if (item != null) {
						stack = new ItemStack(item, 1, itemDamage);
					}
				}
			}
		}
		return stack;
	}

	private void priceCraftedItems() {
		// FMLLog.log.info("in autoPriceCraftedItems");
		Set<ResourceLocation> recipeResourceLocations = CraftingManager.REGISTRY.getKeys();
		boolean priceUpdate = false;

		do {
			// FMLLog.log.info("priceUpdate loop: " + loopCount);
			priceUpdate = false;
			for (ResourceLocation rloc : recipeResourceLocations) {
				IRecipe irecipe = CraftingManager.getRecipe(rloc);
				int itemCost = 0;
				boolean validRecipe = true;
				ItemStack output = irecipe.getRecipeOutput();
				// FMLLog.log.info("Recipe output: " + output.getDisplayName() + "." +
				// output.getItemDamage());
				// FMLLog.log.info("Recipe output price: " + getItemPrice(output));
				if (output == null || output.getItem() == Items.AIR || hasEnchantment(output) || hasPotion(output)) {
					continue;
				}
				if (getItemPrice(output) != -1) {
					// FMLLog.log.info("recipe output price already set.");
					continue;
				}
				// FMLLog.log.info("Starting pricing for " + output.getDisplayName() + "." +
				// output.getItemDamage() + " " + output);
				NonNullList<Ingredient> recipeItems = irecipe.getIngredients();
				for (int i = 0; i < recipeItems.size(); i++) {
					ItemStack stack = null;
					// FMLLog.log.info("Ingredient: " + recipeItems.get(i));
					if (recipeItems.get(i) instanceof OreIngredient) {
						OreIngredient test = (OreIngredient) recipeItems.get(i);
						if (test.getMatchingStacks().length > 0)
							stack = test.getMatchingStacks()[0];
						// TODO iterate and check for priced items
					} else {
						if (recipeItems.get(i).getMatchingStacks().length > 0) {
							stack = recipeItems.get(i).getMatchingStacks()[0];
							// TODO do we need to iterate here?
						}
					}
					if (stack == null)
						continue;
					FMLLog.log.info(
							"recipe ingredient " + i + " " + stack.getDisplayName() + "." + output.getItemDamage());
					// FMLLog.log.info("price: " + getItemPrice(stack));
					if (getItemPrice(stack) > 0) {
						itemCost += getItemPrice(stack);
					} else {
						validRecipe = false;
						// FMLLog.log.info("can't price " + output.getDisplayName() + "." +
						// output.getItemDamage());
						break;
					}
				}
				if (validRecipe && itemCost / output.getCount() > 0) {
					priceUpdate = true;
					if (output.getCount() > 1) {
						itemCost = itemCost / output.getCount();
					}
					try {
						// FMLLog.log.info("Setting price of " + output.getDisplayName() + "." +
						// output.getItemDamage() + " " + output + " to " + itemCost);
						setItemPrice(output, itemCost);
					} catch (Exception e) {
						FMLLog.log.warn(
								"Universal Coins Autopricer: Failed to set item price: " + output.getUnlocalizedName());
					}
				}
			}
		} while (priceUpdate == true);
	}

	private void priceCoins() {
		Item[] coins = new Item[] { UniversalCoins.Items.iron_coin, UniversalCoins.Items.gold_coin,
				UniversalCoins.Items.emerald_coin, UniversalCoins.Items.diamond_coin,
				UniversalCoins.Items.obsidian_coin };
		for (int i = 0; i < coins.length; i++) {
			int itemPrice = UniversalCoins.coinValues[i];
			ucPriceMap.put(coins[i].getRegistryName() + ".0", itemPrice);
		}
	}

	private void priceSmeltedItems() {
		// FMLLog.log.info("In priceSmeltedItems");
		Map<ItemStack, ItemStack> recipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.instance().getSmeltingList();
		for (Entry<ItemStack, ItemStack> recipe : recipes.entrySet()) {
			ItemStack input = recipe.getKey();
			ItemStack output = recipe.getValue();
			String inputName = "";
			String outputName = "";
			try {
				inputName = input.getItem().getRegistryName().toString();
				outputName = output.getItem().getRegistryName().toString();
			} catch (Exception e) {
				continue;
			}
			if (input.getItemDamage() == 32767) {
				input.setItemDamage(0);
			}
			if (ucPriceMap.get(inputName + "." + input.getItemDamage()) != null
					&& ucPriceMap.get(outputName + "." + output.getItemDamage()) != null) {
				int inputValue = ucPriceMap.get(inputName + "." + input.getItemDamage());
				int outputValue = ucPriceMap.get(outputName + "." + output.getItemDamage());
				if (inputValue != -1 && outputValue == -1) {
					FMLLog.log
							.info("Setting price: " + outputName + "." + output.getItemDamage() + "=" + inputValue + 2);
					ucPriceMap.put(outputName + "." + output.getItemDamage(), inputValue + 2);
				}
			}
		}
	}

	private void updateItems() {
		// FMLLog.log.info("Starting updateItems()");
		for (Item item : Item.REGISTRY) {
			if (item == null) {
				continue;
			}
			// FMLLog.log.info("Processing: " + item.getUnlocalizedName());
			if (item.getHasSubtypes()) {
				// FMLLog.log.info(item.getUnlocalizedName() + " has subtypes");
				String baseName = new ItemStack(item, 1).getDisplayName();
				for (int i = 1; i < Integer.MAX_VALUE; i++) {
					try {
						ItemStack previousStack = new ItemStack(item, 1, i - 1);
						ItemStack stack = new ItemStack(item, 1, i);
						if (stack != null) {
							// FMLLog.log.info("Checking " + stack.getUnlocalizedName());
							String previousName = previousStack.getDisplayName();
							String currentName = stack.getDisplayName();
							if (currentName.contentEquals(baseName) || currentName.contentEquals(previousName)
									|| currentName.contains("" + i)) {
								break;
							}
							addItemToPriceMap(stack);
							// FMLLog.log.info("Adding subtype: " + stack.getUnlocalizedName());
						}
					} catch (Exception e) {
						break;
					}
				}
			}

			ItemStack stack = new ItemStack(item, 1);

			Block.getBlockFromItem(item);
			addItemToPriceMap(stack);
		}
	}

	private void updateOreDictionary() {
		// parse oredictionary
		// FMLLog.log.info("in updateOreDictionary");

		for (String ore : OreDictionary.getOreNames()) {
			// FMLLog.log.info("checking oredictionary:" + ore);
			if (!ucPriceMap.containsKey(ore)) {
				// check ore to see if any of the types has a price, use it
				// if true
				List<ItemStack> test = OreDictionary.getOres(ore);
				int itemValue = -1;
				for (int j = 0; j < test.size(); j++) {
					// FMLLog.log.info("ore item:" + test.get(j).getItem().getRegistryName());
					ItemStack itemStack = ((ItemStack) test.get(j));
					if (itemStack.getItemDamage() == OreDictionary.WILDCARD_VALUE) {
						itemStack.setItemDamage(0);
					}
					int subItemValue = getItemPrice(itemStack);
					// FMLLog.log.info("sub item price:" + subItemValue);
					if (subItemValue > 0) {
						itemValue = subItemValue;
					}
				}
				// FMLLog.log.info("Setting price: " + ore + " " + itemValue);
				ucPriceMap.put("oredictionary:" + ore, itemValue);
			}
		}
	}

	private void updatePotions() {
		for (PotionType potiontype : PotionType.REGISTRY) {
			String potionName = potiontype.getRegistryName().toString();
			if (!ucPriceMap.containsKey(potionName)) {
				// FMLLog.log.info("Setting price: " + potionName + "." + -1);
				ucPriceMap.put(potionName, -1);
			}
		}
	}

	private void updateEnchantments() {
		for (ResourceLocation enchantment : Enchantment.REGISTRY.getKeys()) {
			int maxLevel = Enchantment.getEnchantmentByLocation(enchantment.toString()).getMaxLevel();
			for (int i = 1; i <= maxLevel; i++) {
				String fullEnchantName = enchantment.toString() + "." + i;

				if (!ucPriceMap.containsKey(fullEnchantName)) {
					// FMLLog.log.info("Setting price: " + fullEnchantName + "." + -1);
					ucPriceMap.put(fullEnchantName, -1);
				}
			}
		}
	}

	private ResourceLocation getEnchantmentByName(String name) {
		Map<String, ResourceLocation> enchantMap = new HashMap<String, ResourceLocation>(0);

		for (ResourceLocation enchantment : Enchantment.REGISTRY.getKeys()) {
			enchantMap.put(Enchantment.getEnchantmentByLocation(enchantment.toString()).getName(), enchantment);
		}

		return enchantMap.get(name.substring(0, name.length() - 2));
	}

	private void addItemToPriceMap(ItemStack stack) {
		if (!ucPriceMap.containsKey(stack.getItem().getRegistryName() + "." + stack.getItemDamage())) {
			// check ore dictionary and see if we can price this item
			int itemPrice = -1;
			int[] id = null;
			try {
				id = OreDictionary.getOreIDs(stack);
			} catch (Exception e) {
				// fail quietly
			}
			if (id != null && id.length > 0) {
				String oreItemName = OreDictionary.getOreName(id[0]);
				if (ucPriceMap.get("oredictionary:" + oreItemName) != null) {
					itemPrice = ucPriceMap.get("oredictionary:" + oreItemName);
				}
			}
			// FMLLog.log.info("Setting price: " + stack.getItem().getRegistryName() + "." +
			// stack.getItemDamage() + " " + itemPrice);
			ucPriceMap.put(stack.getItem().getRegistryName() + "." + stack.getItemDamage(), itemPrice);
		}
	}

	private ArrayList<String> getEnchantmentList(ItemStack stack) {
		ArrayList<String> enchantments = new ArrayList<String>();
		NBTTagCompound tagCompound = stack.getTagCompound();
		// Books
		NBTTagList enchList = tagCompound.getTagList("StoredEnchantments", Constants.NBT.TAG_COMPOUND);
		// Tools + Weapons
		if (enchList.hasNoTags()) {
			enchList = stack.getTagCompound().getTagList("ench", Constants.NBT.TAG_COMPOUND);
		}
		if (enchList != null) {
			for (int i = 0; i < enchList.tagCount(); i++) {
				NBTTagCompound enchant = ((NBTTagList) enchList).getCompoundTagAt(i);
				short enchId = enchant.getShort("id");
				short lvl = enchant.getShort("lvl");
				enchantments.add(Enchantment.getEnchantmentByID(enchId).getName() + "." + lvl);
			}
		}
		return enchantments;
	}

	public boolean hasEnchantment(ItemStack stack) {
		if (stack.hasTagCompound()) {
			NBTTagCompound tagCompound = stack.getTagCompound();
			return tagCompound.hasKey("ench", 9) || tagCompound.hasKey("StoredEnchantments");
		}
		return false;
	}

	public boolean hasPotion(ItemStack stack) {
		if (stack.hasTagCompound()) {
			NBTTagCompound tagCompound = stack.getTagCompound();
			if (!tagCompound.hasKey("CustomPotionEffects")) {
				return tagCompound.hasKey("Potion");
			}
		}
		return false;
	}

	public String getPotion(ItemStack stack) {
		if (stack.hasTagCompound()) {
			NBTTagCompound tagCompound = stack.getTagCompound();
			String potion = tagCompound.getString("Potion");
			if (!tagCompound.hasKey("CustomPotionEffects") && !potion.contentEquals("")) {
				return potion;
			}
		}
		return "";
	}
} public class UCPlayerPickupEventHandler {

	private World world;
	private String accountNumber;

	@SubscribeEvent
	public void onItemPickup(EntityItemPickupEvent event) {
		if (event.getItem().getItem().getItem() == UniversalCoins.Items.iron_coin
				|| event.getItem().getItem().getItem() == UniversalCoins.Items.gold_coin
				|| event.getItem().getItem().getItem() == UniversalCoins.Items.emerald_coin
				|| event.getItem().getItem().getItem() == UniversalCoins.Items.diamond_coin
				|| event.getItem().getItem().getItem() == UniversalCoins.Items.obsidian_coin) {
			// event.getEntityPlayer().addStat(Achievements.achCoin, 1);
			setWorld(event.getEntityPlayer().world);
			EntityPlayer player = event.getEntityPlayer();
			NonNullList<ItemStack> inventory = player.inventory.mainInventory;
			DecimalFormat formatter = new DecimalFormat("#,###,###,###");
			for (int i = 0; i < inventory.size(); i++) {
				if (inventory.get(i) != null && inventory.get(i).getItem() == UniversalCoins.Items.ender_card) {
					if (!inventory.get(i).hasTagCompound())
						return; // card has not been initialized. Nothing we can
								// do here
					accountNumber = inventory.get(i).getTagCompound().getString("Account");
					FMLLog.log.info("Account: " + accountNumber);
					long accountBalance = UniversalAccounts.getInstance().getAccountBalance(accountNumber);
					if (accountBalance == -1)
						return; // get out of here if the card is invalid
					if (event.getItem().getItem().getCount() == 0)
						return; // no need to notify on zero size stack
					int coinValue = 0;
					int stackSize = event.getItem().getItem().getCount();
					switch (event.getItem().getItem().getUnlocalizedName()) {
					case "item.universalcoins.iron_coin":
						coinValue = UniversalCoins.coinValues[0];
						break;
					case "item.universalcoins.gold_coin":
						coinValue = UniversalCoins.coinValues[1];
						break;
					case "item.universalcoins.emerald_coin":
						coinValue = UniversalCoins.coinValues[2];
						break;
					case "item.universalcoins.diamond_coin":
						coinValue = UniversalCoins.coinValues[3];
						break;
					case "item.universalcoins.obsidian_coin":
						coinValue = UniversalCoins.coinValues[4];
						break;
					}
					if (UniversalAccounts.getInstance().creditAccount(accountNumber, coinValue * stackSize, true)) {
						UniversalAccounts.getInstance().creditAccount(accountNumber, coinValue * stackSize, false);
						event.getItem().getItem().setCount(0);
						player.sendMessage(new TextComponentString(("item.card.deposit") + " "
								+ formatter.format(stackSize * coinValue) + " " + ("general.currency.single")));
						break; // no need to continue. We are done here
					}
				}
			}
		}
	}

	public World getWorld() {
		return world;
	}

	public void setWorld(World world) {
		this.world = world;
	}
} public class VillageGenBank implements IVillageCreationHandler {

	@Override
	public PieceWeight getVillagePieceWeight(Random random, int i) {
		return new StructureVillagePieces.PieceWeight(ComponentVillageBank.class, UniversalCoins.bankGenWeight, random.nextInt(2));
	}

	@Override
	public Class<?> getComponentClass() {
		return ComponentVillageBank.class;
	}

	@Override
	public Village buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List<StructureComponent> pieces, Random random, int p1,
            int p2, int p3, EnumFacing facing, int p5) {
		return ComponentVillageBank.buildComponent(startPiece, pieces, random, p1, p2, p3, facing, p5);
	}

} public class VillageGenShop implements IVillageCreationHandler {

	@Override
	public PieceWeight getVillagePieceWeight(Random random, int i) {
		return new StructureVillagePieces.PieceWeight(ComponentVillageShop.class, UniversalCoins.shopGenWeight, random.nextInt(4));
	}

	@Override
	public Class<?> getComponentClass() {
		return ComponentVillageShop.class;
	}

	@Override
	public Village buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List<StructureComponent> pieces, Random random, int p1,
             int p2, int p3, EnumFacing facing, int p5) {
		return ComponentVillageShop.buildComponent(startPiece, pieces, random, p1, p2, p3, facing, p5);
	}

} public class VillageGenTrade implements IVillageCreationHandler {

	@Override
	public PieceWeight getVillagePieceWeight(Random random, int i) {
		return new StructureVillagePieces.PieceWeight(ComponentVillageTrade.class, UniversalCoins.tradeGenWeight, 1);
	}

	@Override
	public Class<?> getComponentClass() {
		return ComponentVillageTrade.class;
	}

	@Override
	public Village buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List<StructureComponent> pieces, Random random, int p1,
            int p2, int p3, EnumFacing facing, int p5) {
		return ComponentVillageTrade.buildComponent(startPiece, pieces, random, p1, p2, p3, facing, p5);
	}

}
import static net.minecraftforge.fml.relauncher.Side.CLIENT;
import java.lang.reflect.Field;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.command.ICommandManager;
import net.minecraft.command.ServerCommandManager;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.LootEntryItem;
import net.minecraft.world.storage.loot.LootPool;
import net.minecraft.world.storage.loot.RandomValueRange;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraft.world.storage.loot.functions.LootFunction;
import net.minecraft.world.storage.loot.functions.SetCount;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder;
import net.minecraftforge.fml.common.registry.VillagerRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import universalcoins.block.BlockATM;
import universalcoins.block.BlockPackager;
import universalcoins.block.BlockPowerReceiver;
import universalcoins.block.BlockPowerTransmitter;
import universalcoins.block.BlockSafe;
import universalcoins.block.BlockSignal;
import universalcoins.block.BlockTradeStation;
import universalcoins.block.BlockUCStandingSign;
import universalcoins.block.BlockUCWallSign;
import universalcoins.block.BlockVendor;
import universalcoins.block.BlockVendorFrame;
import universalcoins.command.UCBalance;
import universalcoins.command.UCCommand;
import universalcoins.command.UCGive;
import universalcoins.command.UCRebalance;
import universalcoins.command.UCSend;
import universalcoins.item.ItemCatalog;
import universalcoins.item.ItemCoin;
import universalcoins.item.ItemEnderCard;
import universalcoins.item.ItemFifthCoin;
import universalcoins.item.ItemFourthCoin;
import universalcoins.item.ItemLinkCard;
import universalcoins.item.ItemPackage;
import universalcoins.item.ItemSecondCoin;
import universalcoins.item.ItemThirdCoin;
import universalcoins.item.ItemUCCard;
import universalcoins.item.ItemUCSign;
import universalcoins.item.ItemVendorWrench;
import universalcoins.net.ATMWithdrawalMessage;
import universalcoins.net.UCButtonMessage;
import universalcoins.net.UCPackagerServerMessage;
import universalcoins.net.UCSignServerMessage;
import universalcoins.net.UCTileSignMessage;
import universalcoins.net.UCVendorServerMessage;
import universalcoins.render.SignalRenderer;
import universalcoins.render.UCSignRenderer;
import universalcoins.render.VendorBlockRenderer;
import universalcoins.render.VendorFrameRenderer;
import universalcoins.tileentity.TileATM;
import universalcoins.tileentity.TilePackager;
import universalcoins.tileentity.TilePowerReceiver;
import universalcoins.tileentity.TilePowerTransmitter;
import universalcoins.tileentity.TileProtected;
import universalcoins.tileentity.TileSafe;
import universalcoins.tileentity.TileSignal;
import universalcoins.tileentity.TileTradeStation;
import universalcoins.tileentity.TileUCSign;
import universalcoins.tileentity.TileVendor;
import universalcoins.tileentity.TileVendorBlock;
import universalcoins.tileentity.TileVendorFrame;
import universalcoins.util.UCItemPricer;
import universalcoins.util.UCPlayerPickupEventHandler;
import universalcoins.worldgen.VillageGenBank;
import universalcoins.worldgen.VillageGenShop;
import universalcoins.worldgen.VillageGenTrade;
						.setUnlocalizedName(MODID + ".vendor_wrench"));

		// register ItemBlocks
		Block[] blocks = { Blocks.atm, Blocks.packager, Blocks.power_receiver, Blocks.power_transmitter, Blocks.safe,
				Blocks.signalblock, Blocks.tradestation, Blocks.vendor_block, Blocks.vendor_frame };
		for (Block block : blocks) {
			event.getRegistry().register(new ItemBlock(block).setRegistryName(block.getRegistryName())
					.setUnlocalizedName(block.getUnlocalizedName()));
		}
	}

	@SuppressWarnings("unchecked")
	@SubscribeEvent
	@SideOnly(CLIENT)
	public static void registerModels(ModelRegistryEvent event) throws Exception {
		Field[] fields = Items.class.getFields();
		for (Field fid : fields) {
			Item item = (Item) fid.get(null);
			ModelLoader.setCustomModelResourceLocation(item, 0,
					new ModelResourceLocation(item.getRegistryName(), "inventory"));
		}
		ClientRegistry.bindTileEntitySpecialRenderer(TileSignal.class, new SignalRenderer());
		ClientRegistry.bindTileEntitySpecialRenderer(TileVendorBlock.class, new VendorBlockRenderer());
		ClientRegistry.bindTileEntitySpecialRenderer(TileVendorFrame.class, new VendorFrameRenderer());
		ClientRegistry.bindTileEntitySpecialRenderer(TileUCSign.class, new UCSignRenderer());

	}

	@EventHandler
	public void preInit(FMLPreInitializationEvent event) {
		Configuration config = new Configuration(event.getSuggestedConfigurationFile());
		config.load();

		// block protection
		Property blockProtect = config.get("Protection", "Integrated block protection", true,
				"Set to false to disable block protection.");
		blockProtection = blockProtect.getBoolean(true);

		// coin values
		Property coinProperty = config.get("coins", "Coin Values", new int[] { 1, 10, 100, 1000, 10000 },
				"Set coin values. First value is not configureable and will be set to 1");
		coinValues = coinProperty.getIntList();
		coinValues[0] = 1; // Override any user set values.

		// loot
		Property mobDrops = config.get("Loot", "Mob Drops", true,
				"Set to false to disable mobs dropping coins on death.");
		mobsDropCoins = mobDrops.getBoolean(true);
		Property dropAmount = config.get("Loot", "Mob Drop Max", 20,
				"Max mob drop stacksize. Minimum 1. Maximum 64. Default 20.");
		mobDropMax = Math.max(1, Math.min(dropAmount.getInt(20), 64));
		Property dropWeight = config.get("Loot", "Mob Drop Weight", 1,
				"Chance of a mob dropping coins. Higher number means higher chance.");
		mobDropWeight = Math.max(0, Math.min(dropWeight.getInt(1), 100));
		Property dragonMultiplier = config.get("Loot", "Ender Dragon Multiplier", 1000,
				"Obsidian coin stacks dropped for ender dragon kills. Minimum 1. Default 10. Max 1000");
		enderDragonMultiplier = Math.max(1, Math.min(dragonMultiplier.getInt(10), 1000));
		Property dungeonCoins = config.get("Loot", "Dungeon Coins", true,
				"Set to false to disable coins spawning in dungeon chests.");
		coinsInDungeon = dungeonCoins.getBoolean(true);

		// trade station
		Property autoMode = config.get("Trade Station", "Auto mode enabled", true,
				"Set to false to disable the ability to automatically buy or sell items.");
		autoModeEnabled = autoMode.getBoolean(true);
		Property sellRatio = config.get("Trade Station", "Sell Ratio", 0.8,
				"Ratio of sell price to buy price. Set to less than 1.0 to give players a percentage of the full buy price when selling an item. (Range: 0.1 - 1.0)");
		itemSellRatio = Math.max(0.1, Math.min(sellRatio.getDouble(0.8), 1.0));
		Property tsBuyEnabled = config.get("Trade Station", "Trade Station Buy enabled", true,
				"Set to false to disable buying items from trade station.");
		tradeStationBuyEnabled = tsBuyEnabled.getBoolean(true);

		// packager
		Property smallPackage = config.get("Packager", "Small Package Price", 10);
		smallPackage.setComment("Set the price of small package");
		smallPackagePrice = Math.max(1, Math.min(smallPackage.getInt(10), 1000));
		Property medPackage = config.get("Packager", "Medium Package Price", 20);
		medPackage.setComment("Set the price of medium package");
		medPackagePrice = Math.max(1, Math.min(medPackage.getInt(20), 1000));
		Property largePackage = config.get("Packager", "Large Package Price", 40);
		largePackage.setComment("Set the price of large package");
		largePackagePrice = Math.max(1, Math.min(largePackage.getInt(40), 1000));

		// rf utility (power company stuff)
		Property rfWholesale = config.get("RF Utility", "Wholesale rate", 12);
		rfWholesale.setComment("Set payment per 10 kRF of power sold. Default: 12");
		rfWholesaleRate = Math.max(0, rfWholesale.getInt(12));
		Property rfRetail = config.get("RF Utility", "Retail rate", 15);
		rfRetail.setComment("Set payment per 10 kRF of power bought. Default: 15");
		rfRetailRate = Math.max(0, rfRetail.getInt(15));

		// world gen
		Property bankGenProperty = config.get("world generation", "Village bank weight", 8);
		bankGenProperty.setComment("Probability of adding bank to villages. min 0, max 20, default 8.");
		bankGenWeight = Math.max(0, Math.min(bankGenProperty.getInt(8), 20));
		Property shopGenProperty = config.get("world generation", "Village shop weight", 8);
		shopGenProperty.setComment("Probably of adding shop to villages. min 0, max 20, default 8.");
		shopGenWeight = Math.max(0, Math.min(shopGenProperty.getInt(8), 20));
		Property tradeGenProperty = config.get("world generation", "Village trade station weight", 8);
		tradeGenProperty.setComment("Probability of adding trade station to villages. min 0, max 20, default 8.");
		tradeGenWeight = Math.max(0, Math.min(tradeGenProperty.getInt(8), 20));

		Property shopMinPriceProperty = config.get("World Generation", "Minimum shop price", 100);
		shopMinPriceProperty.setComment(
				"Set the minimum price of items for sale in shops as a percent (min=1,max=100,default=100)");
		shopMinPrice = Math.max(1, Math.min(shopMinPriceProperty.getInt(100), 100));
		Property shopMaxPriceProperty = config.get("World Generation", "Maximum shop price", 140);
		shopMaxPriceProperty.setComment(
				"Set the maximum price of items for sale in shops as a percent (min=100,max=300,default=140)");
		shopMaxPrice = Math.max(100, Math.min(shopMaxPriceProperty.getInt(140), 300));

		config.save();

		MinecraftForge.EVENT_BUS.register(new UCPlayerPickupEventHandler());

		// network packet handling
		snw = NetworkRegistry.INSTANCE.newSimpleChannel(MODID);
		snw.registerMessage(UCButtonMessage.class, UCButtonMessage.class, 0, Side.SERVER);
		snw.registerMessage(UCVendorServerMessage.class, UCVendorServerMessage.class, 1, Side.SERVER);
		snw.registerMessage(UCSignServerMessage.class, UCSignServerMessage.class, 2, Side.SERVER);
		snw.registerMessage(UCTileSignMessage.class, UCTileSignMessage.class, 3, Side.CLIENT);