/**
   * Override sounds when walking on block.
   *
   * @param event
   */
  @SideOnly(Side.CLIENT)
  @SubscribeEvent
  public void onPlaySoundAtEntityEvent(PlaySoundAtEntityEvent event) {
    if (event != null && event.name != null && event.name.contains(CarpentersBlocks.MODID)) {
      Entity entity = event.entity;

      /*
       * The function to my knowledge is only used for playing walking sounds
       * at entity, so we'll check for the conditions first.
       */
      if (!isMovingOnGround(entity)) {
        return;
      }

      TEBase TE = getTileEntityAtFeet(entity);
      if (TE != null) {

        // Give SoundType a valid resource by default
        event.name = Blocks.planks.stepSound.getStepResourcePath();

        // Gather accurate SoundType based on block properties
        Block block = BlockProperties.toBlock(getSurfaceItemStack(TE));
        if (!(block instanceof BlockCoverable)) {
          event.name = block.stepSound.getStepResourcePath();
        }
      }
    }
  }
  @SubscribeEvent
  public void onLivingUpdateEvent(LivingUpdateEvent event) {
    Entity entity = event.entityLiving;
    World world = entity.worldObj;

    /*
     * The purpose of the function is to manifest sprint particles
     * and adjust slipperiness when entity is moving on block, so check
     * that the conditions are met first.
     */
    if (!isMovingOnGround(entity)) {
      return;
    }

    TEBase TE = getTileEntityAtFeet(entity);
    if (TE != null) {

      ItemStack itemStack = getSurfaceItemStack(TE);

      /* Spawn sprint particles client-side. */

      if (world.isRemote && entity.isSprinting() && !entity.isInWater()) {
        ParticleHelper.spawnTileParticleAt(entity, itemStack);
      }

      /* Adjust block slipperiness according to cover. */

      Block block = BlockProperties.toBlock(itemStack);
      if (block instanceof BlockCoverable) {
        TE.getBlockType().slipperiness = Blocks.dirt.slipperiness;
      } else {
        TE.getBlockType().slipperiness = block.slipperiness;
      }
    }
  }
  @SideOnly(Side.CLIENT)
  @SubscribeEvent
  public void onPlaySoundEvent(PlaySoundEvent17 event) {
    if (event != null && event.name != null && event.name.contains(CarpentersBlocks.MODID)) {
      if (FMLCommonHandler.instance().getSide() == Side.CLIENT) {
        World world = FMLClientHandler.instance().getClient().theWorld;
        int x = MathHelper.floor_double(event.sound.getXPosF());
        int y = MathHelper.floor_double(event.sound.getYPosF());
        int z = MathHelper.floor_double(event.sound.getZPosF());

        // We'll set a default block type to be safe
        Block block = Blocks.planks;

        // Grab approximate origin, and gather accurate block type
        TEBase TE = getApproximateSoundOrigin(world, x, y, z);
        if (TE != null && TE.hasAttribute(TE.ATTR_COVER[6])) {
          block = BlockProperties.toBlock(BlockProperties.getCoverSafe(TE, 6));
        }

        if (event.name.startsWith("step.")) {
          event.result =
              new PositionedSoundRecord(
                  new ResourceLocation(block.stepSound.getStepResourcePath()),
                  block.stepSound.getVolume() * 0.15F,
                  block.stepSound.getPitch(),
                  x + 0.5F,
                  y + 0.5F,
                  z + 0.5F);
        } else { // "dig." usually
          event.result =
              new PositionedSoundRecord(
                  new ResourceLocation(block.stepSound.getBreakSound()),
                  (block.stepSound.getVolume() + 1.0F) / 2.0F,
                  block.stepSound.getPitch() * 0.8F,
                  x + 0.5F,
                  y + 0.5F,
                  z + 0.5F);
        }
      }
    }
  }
  /**
   * Gets an {@link ItemStack} that best represents the surface of a Carpenter's Block.
   *
   * <p>The top side cover and any overlays are taken into consideration.
   *
   * @param TE
   * @return
   */
  private ItemStack getSurfaceItemStack(TEBase TE) {
    // Check for top side cover
    int effectiveSide = TE.hasAttribute(TE.ATTR_COVER[1]) ? 1 : 6;
    ItemStack itemStack = BlockProperties.getCover(TE, effectiveSide);

    // Check for overlay on cover
    if (TE.hasAttribute(TE.ATTR_OVERLAY[effectiveSide])) {
      Overlay overlay =
          OverlayHandler.getOverlayType(TE.getAttribute(TE.ATTR_OVERLAY[effectiveSide]));
      if (OverlayHandler.coversFullSide(overlay, 1)) {
        itemStack = overlay.getItemStack();
      }
    }

    return itemStack;
  }
  @SideOnly(Side.CLIENT)
  @SubscribeEvent
  /** Grabs mouse scroll events for slope selection. */
  public void onMouseEvent(MouseEvent event) {
    // We only want to process wheel events
    if (event.button < 0) {
      EntityPlayer entityPlayer = Minecraft.getMinecraft().thePlayer;

      if (entityPlayer != null && entityPlayer.isSneaking()) {
        ItemStack itemStack = entityPlayer.getHeldItem();
        if (itemStack != null
            && itemStack.getItem() instanceof ItemBlock
            && BlockProperties.toBlock(itemStack).equals(BlockRegistry.blockCarpentersSlope)) {
          if (event.dwheel != 0) {
            PacketHandler.sendPacketToServer(
                new PacketSlopeSelect(entityPlayer.inventory.currentItem, event.dwheel > 0));
          }
          event.setCanceled(true);
        }
      }
    }
  }
  @SubscribeEvent
  /**
   * Used to store side clicked and also forces onBlockActivated event when entityPlayer is sneaking
   * and activates block with the Carpenter's Hammer.
   */
  public void onPlayerInteractEvent(PlayerInteractEvent event) {
    if (event.entityPlayer.worldObj.isRemote || event.isCanceled()) {
      return;
    }

    Block block = event.entity.worldObj.getBlock(event.x, event.y, event.z);

    if (block instanceof BlockCoverable) {

      eventFace = event.face;
      eventEntityPlayer = event.entityPlayer;

      ItemStack itemStack = eventEntityPlayer.getHeldItem();

      MovingObjectPosition object =
          getMovingObjectPositionFromPlayer(eventEntityPlayer.worldObj, eventEntityPlayer);

      if (object != null) {
        hitX = (float) object.hitVec.xCoord - event.x;
        hitY = (float) object.hitVec.yCoord - event.y;
        hitZ = (float) object.hitVec.zCoord - event.z;
      } else {
        hitX = hitY = hitZ = 1.0F;
      }

      switch (event.action) {
        case LEFT_CLICK_BLOCK:
          boolean toolEquipped =
              itemStack != null
                  && (itemStack.getItem() instanceof ICarpentersHammer
                      || itemStack.getItem() instanceof ICarpentersChisel);

          /*
           * Creative mode doesn't normally invoke onBlockClicked(), but rather it tries
           * to destroy the block.
           *
           * We'll invoke it here when a Carpenter's tool is being held.
           */

          if (toolEquipped && eventEntityPlayer.capabilities.isCreativeMode) {
            block.onBlockClicked(
                eventEntityPlayer.worldObj, event.x, event.y, event.z, eventEntityPlayer);
          }

          break;
        case RIGHT_CLICK_BLOCK:

          /*
           * Make sure sneak right-click makes it through the onBlockActivate.
           */

          if (eventEntityPlayer.isSneaking()
              && !(itemStack != null
                  && itemStack.getItem() instanceof ItemBlock
                  && !BlockProperties.isOverlay(itemStack))) {
            block.onBlockActivated(
                eventEntityPlayer.worldObj,
                event.x,
                event.y,
                event.z,
                eventEntityPlayer,
                event.face,
                1.0F,
                1.0F,
                1.0F);
          }

          break;
        default:
          {
          }
      }
    }
  }