@Override
  /** Rotates safe so that it faces player. */
  protected boolean onHammerLeftClick(TEBase TE, EntityPlayer entityPlayer) {
    int facing = BlockProperties.getOppositeFacing(entityPlayer);
    ForgeDirection dir = BlockProperties.getDirectionFromFacing(facing);

    if (dir != Safe.getFacing(TE)) {
      Safe.setFacing(TE, facing);
      return true;
    } else {
      return false;
    }
  }
  @Override
  /** Called when the block is placed in the world. */
  public void onBlockPlacedBy(
      World world, int x, int y, int z, EntityLivingBase entityLiving, ItemStack itemStack) {
    TEBase TE = getTileEntityStrict(world, x, y, z);

    Safe.setFacing(TE, BlockProperties.getOppositeFacing(entityLiving));

    super.onBlockPlacedBy(world, x, y, z, entityLiving, itemStack);
  }
  @Override
  /**
   * Gets the hardness of block at the given coordinates in the given world, relative to the ability
   * of the given EntityPlayer.
   */
  public float getPlayerRelativeBlockHardness(
      EntityPlayer entityPlayer, World world, int x, int y, int z) {
    TEBase TE = getTileEntityStrict(world, x, y, z);

    if (Safe.isOpen(TE)
        || !PlayerPermissions.canPlayerEdit(TE, TE.xCoord, TE.yCoord, TE.zCoord, entityPlayer)) {
      return -1; // Unbreakable
    } else {
      return super.getPlayerRelativeBlockHardness(entityPlayer, world, x, y, z);
    }
  }
  @Override
  /** Cycles locked state. */
  protected boolean onHammerRightClick(TEBase TE, EntityPlayer entityPlayer) {
    if (entityPlayer.isSneaking()) {

      boolean locked = !Safe.isLocked(TE);

      Safe.setLocked(TE, locked);

      if (locked) {
        Safe.setAutoPerm(TE, Safe.AUTOMATION_DISABLED);
      } else {
        Safe.setAutoPerm(TE, Safe.AUTOMATION_ALL);
      }

      if (locked) {
        ChatHandler.sendMessageToPlayer("message.safe_lock.name", entityPlayer);
      } else {
        ChatHandler.sendMessageToPlayer("message.safe_unlock.name", entityPlayer);
      }

      return true;
    } else {
      int autoPerm = Safe.getAutoPerm(TE);

      if (++autoPerm > 3) {
        autoPerm = 0;
      }

      Safe.setAutoPerm(TE, autoPerm);

      switch (autoPerm) {
        case Safe.AUTOMATION_ALL:
          ChatHandler.sendMessageToPlayer("message.automation_all.name", entityPlayer);
          break;
        case Safe.AUTOMATION_DISABLED:
          ChatHandler.sendMessageToPlayer("message.automation_disabled.name", entityPlayer);
          break;
        case Safe.AUTOMATION_RECEIVE:
          ChatHandler.sendMessageToPlayer("message.automation_insert.name", entityPlayer);
          break;
        case Safe.AUTOMATION_SEND:
          ChatHandler.sendMessageToPlayer("message.automation_extract.name", entityPlayer);
          break;
      }
    }

    return true;
  }
  @Override
  /**
   * Checks if the block is a solid face on the given side, used by placement logic.
   *
   * @param world The current world
   * @param x X Position
   * @param y Y position
   * @param z Z position
   * @param side The side to check
   * @return True if the block is solid on the specified side.
   */
  public boolean isSideSolid(IBlockAccess world, int x, int y, int z, ForgeDirection side) {
    TEBase TE = getTileEntityStrict(world, x, y, z);

    if (TE != null) {
      if (isBlockSolid(world, x, y, z)) {
        return side != Safe.getFacing(TE);
      }
    }

    return false;
  }
  @Override
  /** Called upon block activation (right click on the block.) */
  protected void postOnBlockActivated(
      TEBase TE,
      EntityPlayer entityPlayer,
      int side,
      float hitX,
      float hitY,
      float hitZ,
      List<Boolean> altered,
      List<Boolean> decInv) {
    if (!Safe.isOpen(TE) && canPlayerActivate(TE, entityPlayer)) {

      TECarpentersSafe TE_safe = (TECarpentersSafe) TE;
      ItemStack itemStack = entityPlayer.getHeldItem();

      if (itemStack != null && itemStack.getItem().equals(Items.gold_ingot)) {
        if (!TE_safe.hasUpgrade()) {
          if (TE_safe.incSizeInventory()) {
            TE.getWorldObj().markBlockForUpdate(TE.xCoord, TE.yCoord, TE.zCoord);
            decInv.add(true);
            return;
          }
        }
      }

      if (!decInv.contains(true)) {
        entityPlayer.displayGUIChest((TECarpentersSafe) TE);
      }
    } else {
      ChatHandler.sendMessageToPlayer("message.block_lock.name", entityPlayer);
    }

    /*
     * Safe should always return true because it either warns the player
     * that it is locked, or it returns the GUI.
     */
    altered.add(true);
  }
 /** Returns whether player is allowed to activate this block. */
 @Override
 protected boolean canPlayerActivate(TEBase TE, EntityPlayer entityPlayer) {
   return PlayerPermissions.canPlayerEdit(TE, TE.xCoord, TE.yCoord, TE.zCoord, entityPlayer)
       || !Safe.isLocked(TE);
 }