@Override
  public boolean rotateBlock(World world, int x, int y, int z, ForgeDirection axis) {
    if (Arrays.asList(getRotationAxes()).contains(axis)) {
      TEBase TE = getTileEntity(world, x, y, z);
      if (TE != null && data.isFreestanding(TE)) {
        int side = data.getDirection(TE).ordinal() == data.DIR_ON_X ? data.DIR_ON_Z : data.DIR_ON_X;
        return data.setDirection(TE, ForgeDirection.getOrientation(side));
      }
    }

    return super.rotateBlock(world, x, y, z, axis);
  }
  @Override
  /** Updates the blocks bounds based on its current state. Args: world, x, y, z */
  public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int x, int y, int z) {
    TEBase TE = getTileEntity(blockAccess, x, y, z);

    if (TE != null) {
      ForgeDirection dir = data.getDirection(TE);
      switch (dir) {
        case DOWN: // DIR_ON_X
          setBlockBounds(0.0F, 0.0F, 0.375F, 1.0F, 1.0F, 0.625F);
          break;
        case UP: // DIR_ON_Z
          setBlockBounds(0.375F, 0.0F, 0.0F, 0.625F, 1.0F, 1.0F);
          break;
        default:
          setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.1875F, dir);
      }
    }
  }
  @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) {
    super.onBlockPlacedBy(world, x, y, z, entityLiving, itemStack);

    if (!entityLiving.isSneaking()) {
      // Copy type and direction of adjacent ladder type
      for (int side = 0; side < 2; ++side) {
        TEBase TE = getTileEntity(world, x, y, z);
        ForgeDirection dir = ForgeDirection.getOrientation(side);
        if (world.getBlock(x, y - dir.offsetY, z).equals(this)) {
          TEBase TE_adj = (TEBase) world.getTileEntity(x, y - dir.offsetY, z);
          data.setType(TE, data.getType(TE_adj));
          data.setDirection(TE, data.getDirection(TE_adj));
        }
      }
    }
  }