/**
  * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
  */
 @Override
 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) {
   return par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)
       || par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)
       || par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)
       || par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH);
 }
  /** called before onBlockPlacedBy by ItemBlock and ItemReed */
  @Override
  public int onBlockPlaced(
      World par1World,
      int par2,
      int par3,
      int par4,
      int par5,
      float par6,
      float par7,
      float par8,
      int par9) {
    int direction = par9 % 4;
    final int type = par9 / 4;

    if ((false || par5 == 2) && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) {
      direction = 0;
    } else if ((false || par5 == 3) && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) {
      direction = 1;
    } else if ((false || par5 == 4) && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) {
      direction = 2;
    } else if ((false || par5 == 5) && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) {
      direction = 3;
    }

    par1World.setBlockMetadataWithNotify(par2, par3, par4, type * 4 + direction, 2);
    return type * 4 + direction;
  }
  /**
   * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed
   * (coordinates passed are their own) Args: x, y, z, neighbor blockID
   */
  @Override
  public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
    final int type = par1World.getBlockMetadata(par2, par3, par4) / 4;
    final int var6 = par1World.getBlockMetadata(par2, par3, par4) % 4;
    boolean canStay = false;

    if (var6 == 0 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) {
      canStay = true;
    }

    if (var6 == 1 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) {
      canStay = true;
    }

    if (var6 == 2 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) {
      canStay = true;
    }

    if (var6 == 3 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) {
      canStay = true;
    }

    if (!canStay) {
      dropBlockAsItem(par1World, par2, par3, par4, type * 4 + var6, 0);
      par1World.setBlockToAir(par2, par3, par4); // Remove Block
    }

    super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
  }
  public int func_85104_a(
      World par1World,
      int par2,
      int par3,
      int par4,
      int par5,
      float par6,
      float par7,
      float par8,
      int par9) {
    int var10 = par9;

    if ((var10 == 0 || par5 == 2) && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) {
      var10 = 2;
    }

    if ((var10 == 0 || par5 == 3) && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) {
      var10 = 3;
    }

    if ((var10 == 0 || par5 == 4) && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) {
      var10 = 4;
    }

    if ((var10 == 0 || par5 == 5) && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) {
      var10 = 5;
    }

    return var10;
  }
  /**
   * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed
   * (coordinates passed are their own) Args: x, y, z, neighbor blockID
   */
  @Override
  public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
    if (this.dropTorchIfCantStay(par1World, par2, par3, par4)) {
      int var6 = par1World.getBlockMetadata(par2, par3, par4);
      boolean var7 = false;

      if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST, true) && var6 == 1) {
        var7 = true;
      }

      if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST, true) && var6 == 2) {
        var7 = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH, true) && var6 == 3) {
        var7 = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH, true) && var6 == 4) {
        var7 = true;
      }

      if (!this.canPlaceTorchOn(par1World, par2, par3 - 1, par4) && var6 == 5) {
        var7 = true;
      }

      if (var7) {
        this.dropBlockAsItem(
            par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
        par1World.setBlock(par2, par3, par4, 0);
      }
    }
  }
  /**
   * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY,
   * hitZ, block metadata
   */
  @Override
  public int onBlockPlaced(
      World par1World,
      int par2,
      int par3,
      int par4,
      int par5,
      float par6,
      float par7,
      float par8,
      int par9) {
    int var10 = par9;

    if (par5 == 1 && this.canPlaceTorchOn(par1World, par2, par3 - 1, par4)) {
      var10 = 5;
    }

    if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH, true)) {
      var10 = 4;
    }

    if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH, true)) {
      var10 = 3;
    }

    if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST, true)) {
      var10 = 2;
    }

    if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST, true)) {
      var10 = 1;
    }

    return var10;
  }
 @Override
 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) {
   ForgeDirection dir = ForgeDirection.getOrientation(par5);
   return (dir == DOWN && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN))
       || (dir == UP && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP))
       || (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH))
       || (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH))
       || (dir == WEST && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST))
       || (dir == EAST && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST));
 }
  @Override
  public boolean puffSmoke(
      World world, int x, int y, int z, float num, float speedX, float speedY) {
    if (world.getBlockMetadata(x, y, z) > 0) return false;

    IChimney chimney = (IChimney) Block.blocksList[world.getBlockId(x, y, z)];
    if (chimney == null) {
      return false;
    }

    Random rand = new Random();

    if (Block.blocksList[world.getBlockId(x, y + 1, z)] instanceof IChimney) {
      IChimney chimney2 = (IChimney) Block.blocksList[world.getBlockId(x, y + 1, z)];
      return chimney2.puffSmoke(world, x, y + 1, z, num, speedX, speedY);
    }

    for (int a = 0; a < 30 * num; a++) {
      if (!world.isBlockSolidOnSide(x, y + 1, z, ForgeDirection.DOWN))
        world.spawnParticle(
            "largesmoke",
            x + 0.5F,
            y + 1,
            z + 0.5F,
            (rand.nextFloat() - 0.5F) / 6 * speedX,
            0.065F * speedY,
            (rand.nextFloat() - 0.5F) / 6 * speedX);
    }

    return true;
  }
  /** Called whenever the block is added into the world. Args: world, x, y, z */
  @Override
  public void onBlockAdded(World par1World, int par2, int par3, int par4) {
    if (par1World.getBlockMetadata(par2, par3, par4) == 0) {
      if (par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST, true)) {
        par1World.setBlockMetadataWithNotify(par2, par3, par4, 1, 0);
      } else if (par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST, true)) {
        par1World.setBlockMetadataWithNotify(par2, par3, par4, 2, 0);
      } else if (par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH, true)) {
        par1World.setBlockMetadataWithNotify(par2, par3, par4, 3, 0);
      } else if (par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH, true)) {
        par1World.setBlockMetadataWithNotify(par2, par3, par4, 4, 0);
      } else if (this.canPlaceTorchOn(par1World, par2, par3 - 1, par4)) {
        par1World.setBlockMetadataWithNotify(par2, par3, par4, 5, 0);
      }
    }

    this.dropTorchIfCantStay(par1World, par2, par3, par4);
  }
  /**
   * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed
   * (coordinates passed are their own) Args: x, y, z, neighbor blockID
   */
  public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) {
    if (!par1World.isRemote) {
      if (this.powered && !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
        par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, 4);
      } else if (!this.powered && par1World.isBlockIndirectlyGettingPowered(par2, par3, par4)) {
        int m = par1World.getBlockMetadata(par2, par3, par4);
        par1World.setBlockAndMetadataWithNotify(
            par2, par3, par4, MinecraftPlusBase.holidaylights_1Active.blockID, m);
      }
    }
    int var6 = par1World.getBlockMetadata(par2, par3, par4);
    boolean var7 = false;

    if (var6 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) {
      var7 = true;
    }

    if (var6 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) {
      var7 = true;
    }

    if (var6 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) {
      var7 = true;
    }

    if (var6 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) {
      var7 = true;
    }

    if (!var7) {
      this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
      par1World.setBlockWithNotify(par2, par3, par4, 0);
    }

    super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
  }
  public void checkPlacement(World par1World, int par2, int par3, int par4, int par5) {
    if (this.checkIfAttachedToBlock(par1World, par2, par3, par4)) {
      int i1 = par1World.getBlockMetadata(par2, par3, par4) & 7;
      boolean flag = false;

      if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && i1 == 1) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && i1 == 2) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && i1 == 3) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && i1 == 4) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && i1 == 5) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && i1 == 6) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && i1 == 0) {
        flag = true;
      }

      if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && i1 == 7) {
        flag = true;
      }

      if (flag) {
        this.dropBlockAsItem(
            par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
        par1World.setBlockToAir(par2, par3, par4);
      }
    }
  }
  protected void generateChest(World world, int x, int y, int z, Random random) {
    int[] face = new int[] {2, 5, 3, 4};
    if (!world.isBlockSolidOnSide(x, y - 1, z, ForgeDirection.DOWN)) {
      return;
    }
    world.setBlock(x, y, z, RumBlock.blockLockedChest.blockID, face[random.nextInt(4)], 2);
    TileEntityLockedChest tileEntityLockedChest =
        (TileEntityLockedChest) world.getBlockTileEntity(x, y, z);

    if (tileEntityLockedChest != null) {
      for (int itemNum = 0; itemNum < LockedChestInfo.lockedChestContents.getMax(); ++itemNum) {
        ItemStack chestInItem = LockedChestInfo.lockedChestContents.getOneItem(random);

        if (chestInItem != null) {
          tileEntityLockedChest.setInventorySlotContents(
              random.nextInt(tileEntityLockedChest.getSizeInventory()), chestInItem);
        }
      }
    }
  }
  @Override
  public int onBlockPlaced(
      World par1World,
      int par2,
      int par3,
      int par4,
      int par5,
      float par6,
      float par7,
      float par8,
      int par9) {
    int j1 = par9 & 8;
    int k1 = par9 & 7;
    byte b0 = -1;

    if (par5 == 0 && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN)) {
      b0 = 0;
    }

    if (par5 == 1 && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP)) {
      b0 = 5;
    }

    if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) {
      b0 = 4;
    }

    if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) {
      b0 = 3;
    }

    if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) {
      b0 = 2;
    }

    if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) {
      b0 = 1;
    }

    return b0 + j1;
  }
  private boolean placeBlock(
      Minecraft minecraft,
      World world,
      EntityPlayer player,
      int x,
      int y,
      int z,
      int itemId,
      int itemDamage) {
    if (!isValidOrientation(player, x, y, z, itemId, itemDamage)) {
      return false;
    }

    if (SchematicWorld.isFluidContainer(itemId) || itemId == Item.sign.itemID) {
      return false;
    }

    int side = 0;
    float offsetY = 0.0f;
    ForgeDirection direction = ForgeDirection.DOWN;
    boolean[] blocks =
        new boolean[] {
          world.getBlockId(x, y + 1, z) > 0,
          world.getBlockId(x, y - 1, z) > 0,
          world.getBlockId(x, y, z + 1) > 0,
          world.getBlockId(x, y, z - 1) > 0,
          world.getBlockId(x + 1, y, z) > 0,
          world.getBlockId(x - 1, y, z) > 0
        };

    for (int i = 0; i < 6; i++) {
      if (blocks[i]) {
        direction = ForgeDirection.getOrientation(i).getOpposite();
        break;
      }
    }

    if (SchematicWorld.isMetadataSensitive(itemId)) {
      int itemDamageInHand = 0xF;
      if (SchematicWorld.isTorch(itemId)) {
        switch (itemDamage) {
          case 1:
            direction = ForgeDirection.WEST;
            break;
          case 2:
            direction = ForgeDirection.EAST;
            break;
          case 3:
            direction = ForgeDirection.NORTH;
            break;
          case 4:
            direction = ForgeDirection.SOUTH;
            break;
          case 5:
            direction = ForgeDirection.DOWN;
            break;
        }

        if (direction == ForgeDirection.DOWN) {
          if (world.doesBlockHaveSolidTopSurface(x, y - 1, z)) {
            itemDamageInHand = 0;
          }
        } else {
          if (world.isBlockSolidOnSide(
              x + direction.offsetX,
              y + direction.offsetY,
              z + direction.offsetZ,
              direction,
              false)) {
            itemDamageInHand = 0;
          }
        }
      } else if (SchematicWorld.isBlock(itemId)) {
        itemDamageInHand = itemDamage;
      } else if (SchematicWorld.isSlab(itemId)) {
        if ((itemDamage & 0x8) != 0 && direction == ForgeDirection.DOWN) {
          direction = ForgeDirection.UP;
        } else if ((itemDamage & 0x8) == 0 && direction == ForgeDirection.UP) {
          direction = ForgeDirection.DOWN;
        }
        offsetY = (itemDamage & 0x8) == 0x0 ? 0.0f : 1.0f;
        itemDamageInHand = itemDamage & 0x7;
      } else if (SchematicWorld.isPistonBase(itemId)) {
        itemDamageInHand = 0;
      } else if (SchematicWorld.isDoubleSlab(itemId)) {
        itemDamageInHand = itemDamage;
      } else if (SchematicWorld.isContainer(itemId)) {
        itemDamageInHand = 0;
      } else if (SchematicWorld.isButton(itemId)) {
        switch (itemDamage & 0x7) {
          case 0x1:
            direction = ForgeDirection.WEST;
            break;
          case 0x2:
            direction = ForgeDirection.EAST;
            break;
          case 0x3:
            direction = ForgeDirection.NORTH;
            break;
          case 0x4:
            direction = ForgeDirection.SOUTH;
            break;
          default:
            return false;
        }

        if (world.isBlockSolidOnSide(
            x + direction.offsetX,
            y + direction.offsetY,
            z + direction.offsetZ,
            direction,
            false)) {
          itemDamageInHand = 0;
        } else {
          return false;
        }
      } else if (SchematicWorld.isPumpkin(itemId)) {
        if (world.doesBlockHaveSolidTopSurface(x, y - 1, z)) {
          itemDamageInHand = 0;
        } else {
          return false;
        }
      } else if (itemId == Item.redstoneRepeater.itemID) {
        itemDamageInHand = 0;
      } else if (itemId == Block.anvil.blockID) {
        switch (itemDamage & 0xC) {
          case 0x0:
            itemDamageInHand = 0;
            break;
          case 0x4:
            itemDamageInHand = 1;
            break;
          case 0x8:
            itemDamageInHand = 2;
            break;
          default:
            return false;
        }
      } else if (itemId == Block.fenceGate.blockID) {
        itemDamageInHand = 0;
      } else if (itemId == Block.trapdoor.blockID) {
        switch (itemDamage & 0x3) {
          case 0x0:
            direction = ForgeDirection.SOUTH;
            break;
          case 0x1:
            direction = ForgeDirection.NORTH;
            break;
          case 0x2:
            direction = ForgeDirection.EAST;
            break;
          case 0x3:
            direction = ForgeDirection.WEST;
            break;
          default:
            return false;
        }

        if ((itemDamage & 0x8) != 0) {
          offsetY = 0.75f;
        }

        if (world.isBlockSolidOnSide(
            x + direction.offsetX,
            y + direction.offsetY,
            z + direction.offsetZ,
            direction,
            false)) {
          itemDamageInHand = 0;
        } else {
          return false;
        }
      } else {
        return false;
      }

      if (!swapToItem(player.inventory, itemId, itemDamageInHand)) {
        return false;
      }
    } else {
      if (!swapToItem(player.inventory, itemId)) {
        return false;
      }

      if (SchematicWorld.isStair(itemId)) {
        direction = (itemDamage & 0x4) == 0x0 ? ForgeDirection.DOWN : ForgeDirection.UP;
      } else if (Block.wood.blockID == itemId) {
        if ((itemDamage & 0xC) == 0x00) {
          direction = ForgeDirection.DOWN;
        } else if ((itemDamage & 0xC) == 0x04) {
          direction = ForgeDirection.EAST;
        } else if ((itemDamage & 0xC) == 0x08) {
          direction = ForgeDirection.NORTH;
        }
      }
    }

    side = getSide(direction);
    if (side != 255 && blocks[side] || !this.settings.placeAdjacent) {
      return placeBlock(minecraft, world, player, x, y, z, direction, 0.0f, offsetY, 0.0f);
    }

    return false;
  }