Ejemplo n.º 1
0
int PacketHandler::player_block_placement(User *user)
{
  if(!user->buffer.haveData(12))
  {
    return PACKET_NEED_MORE_DATA;
  }
  int8_t y = 0, direction = 0;
  int16_t newblock = 0;
  int32_t x, z = 0;
  /* replacement of block */
  uint8_t oldblock = 0;
  uint8_t metadata = 0;
  /* neighbour blocks */
  uint8_t block = 0;
  uint8_t meta  = 0;
  int8_t count  = 0;
  int16_t health = 0;
  BlockBasic* blockcb;
  BlockDefault blockD;


  user->buffer >> x >> y >> z >> direction >> newblock;

  if(newblock >= 0)
  {
    if(!user->buffer.haveData(2))
    {
      return PACKET_NEED_MORE_DATA;
    }
    user->buffer >> count >> health;
  }
  user->buffer.removePacket();

  
  ItemBasic* itemcb;
  if(x==-1 && y==-1 && z==-1)
  {
    // Right clicked without pointing at a tile
    Item *item = &(user->inv[user->curItem+36]);
    if ((static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int8_t>*>(Mineserver::get()->plugin()->getHook("ItemRightClickPre")))->doUntilFalse(user->nick.c_str(), x, y, z, item->getType(),direction))
    {
      return PACKET_OK;
    }


    for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getItemCB().size(); i++)
    {
      itemcb = Mineserver::get()->plugin()->getItemCB()[i];
      if(itemcb!=NULL && itemcb->affectedItem(newblock))
      {
        itemcb->onRightClick(user, item);
      }
    }
    return PACKET_OK;
  }

  if (!Mineserver::get()->map(user->pos.map)->getBlock(x, y, z, &oldblock, &metadata))
  {
    blockD.revertBlock(user,x,y,z,user->pos.map);
    return PACKET_OK;
  }
  
  /* Protocol docs say this should be what interacting is. */
  if(oldblock != BLOCK_AIR)
  {
    (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("PlayerBlockInteract")))->doAll(user->nick.c_str(), x, y, z);
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(oldblock))
        {
          //This should actually make the boolean do something. Maybe.
          if(blockcb->onInteract(user, x,y,z,user->pos.map))
          {
            blockD.revertBlock(user,x,y,z,user->pos.map);
            return PACKET_OK;
          }
          else
          {
            break;
          }
        }
      }
  }
  bool foundFromInventory = false;

  #define INV_TASKBAR_START 36
  if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].getType() == newblock && newblock != -1)
  {
    foundFromInventory = true;
  }
  #undef INV_TASKBAR_START


  // TODO: Handle processing of
  if(direction == -1 || !foundFromInventory)
  {
    blockD.revertBlock(user,x,y,z,user->pos.map);
    return PACKET_OK;
  }

  // Minecart testing!!
  if(newblock == ITEM_MINECART && Mineserver::get()->map(user->pos.map)->getBlock(x, y, z, &oldblock, &metadata))
  {
    if (oldblock != BLOCK_MINECART_TRACKS)
    {
      return PACKET_OK;
    }

    LOG(INFO, "Packets", "Spawn minecart");
    int32_t EID=generateEID();
    Packet pkt;
    // MINECART
    pkt << PACKET_ADD_OBJECT << (int32_t)EID << (int8_t)10 << (int32_t)(x*32+16) << (int32_t)(y*32) << (int32_t)(z*32+16);
    user->sendAll((uint8_t *)pkt.getWrite(), pkt.getWriteLen());
  }

  if (newblock == -1 && newblock != ITEM_SIGN)
  {
#ifdef _DEBUG
     LOG(DEBUG, "Packets", "ignoring: "+dtos(newblock));
#endif
     return PACKET_OK;
  }

  if(y < 0)
  {
    return PACKET_OK;
  }

#ifdef _DEBUG
  LOG(DEBUG,"Packets", "Block_placement: "+dtos(newblock)+" ("+dtos(x)+","+dtos((int)y)+","+dtos(z)+") dir: "+dtos((int)direction));
#endif

  if (direction)
  {
    direction = 6-direction;
  }

  //if (Mineserver::get()->map()->getBlock(x, y, z, &oldblock, &metadata))
  {
    uint8_t oldblocktop;
    uint8_t metadatatop;
    int8_t check_y = y;
    int32_t check_x = x;
    int32_t check_z = z;

    /* client doesn't give us the correct block for lava and water, check block above */
    switch(direction)
    {
      case BLOCK_BOTTOM: check_y--;  break;
      case BLOCK_TOP:    check_y++;  break;
      case BLOCK_NORTH:  check_x++;  break;
      case BLOCK_SOUTH:  check_x--;  break;
      case BLOCK_EAST:   check_z++;  break;
      case BLOCK_WEST:   check_z--;  break;
      default:                       break;
    }

    if (Mineserver::get()->map(user->pos.map)->getBlock(check_x, check_y, check_z, &oldblocktop, &metadatatop) && 
        (oldblocktop == BLOCK_LAVA || oldblocktop == BLOCK_STATIONARY_LAVA ||
         oldblocktop == BLOCK_WATER || oldblocktop == BLOCK_STATIONARY_WATER))
    {
      /* block above needs replacing rather then the block sent by the client */

      // TODO: Does this require some form of recursion for multiple water/lava blocks?

      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        {
          blockcb->onReplace(user, newblock,check_x,check_y,check_z,user->pos.map,direction);
        }
      }

      if ((static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int16_t>*>(Mineserver::get()->plugin()->getHook("BlockReplacePre")))->doUntilFalse(user->nick.c_str(), check_x, check_y, check_z, oldblock, newblock))
      {
        blockD.revertBlock(user,x,y,z,user->pos.map);
        return PACKET_OK;
      }
      (static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int16_t>*>(Mineserver::get()->plugin()->getHook("BlockReplacePost")))->doAll(user->nick.c_str(), check_x, check_y, check_z, oldblock, newblock);
    }
    else
    {
/*      for(int i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        {
          blockcb->onReplace(user, newblock,check_x,check_y,check_z,user->pos.map,direction);
        }
      }*/

      if ((static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int16_t>*>(Mineserver::get()->plugin()->getHook("BlockReplacePre")))->doUntilFalse(user->nick.c_str(), x, y, z, oldblock, newblock))
      {
        blockD.revertBlock(user,x,y,z,user->pos.map);
        return PACKET_OK;
      }
      (static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int16_t>*>(Mineserver::get()->plugin()->getHook("BlockReplacePost")))->doAll(user->nick.c_str(), x, y, z, oldblock, newblock);
    }

    if ((static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int8_t>*>(Mineserver::get()->plugin()->getHook("BlockPlacePre")))->doUntilFalse(user->nick.c_str(), x, y, z, newblock,direction))
    {
      blockD.revertBlock(user,x,y,z,user->pos.map);
      return PACKET_OK;
    }

    /* We pass the newblock to the newblock's onPlace callback because
    the callback doesn't know what type of block we're placing. Instead
    the callback's job is to describe the behaviour when placing the
    block down, not to place any specifically block itself. */
    for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
    {
      blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
      if(blockcb!=NULL && blockcb->affectedBlock(newblock))
      {
        if(blockcb->onPlace(user, newblock,x,y,z,user->pos.map,direction)){
          blockD.revertBlock(user,x,y,z,user->pos.map);
          return PACKET_OK;
        }else{
          break;
        }
      }
    }
    (static_cast<Hook6<bool,const char*,int32_t,int8_t,int32_t,int16_t,int8_t>*>(Mineserver::get()->plugin()->getHook("BlockPlacePost")))->doAll(user->nick.c_str(), x, y, z, newblock,direction);

    /* notify neighbour blocks of the placed block */
    if (Mineserver::get()->map(user->pos.map)->getBlock(x+1, y, z, &block, &meta) && block != BLOCK_AIR)
    {
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        {
          blockcb->onNeighbourPlace(user, newblock,x+1,y,z,user->pos.map,direction);
        }
      }

      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user->nick.c_str(), x+1, y, z);
    }

    if (Mineserver::get()->map(user->pos.map)->getBlock(x-1, y, z, &block, &meta) && block != BLOCK_AIR)
    {
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      { 
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        { 
          blockcb->onNeighbourPlace(user, newblock,x-1,y,z,user->pos.map,direction);
        } 
      } 
      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user->nick.c_str(), x-1, y, z);
    }

    if (Mineserver::get()->map(user->pos.map)->getBlock(x, y+1, z, &block, &meta) && block != BLOCK_AIR)
    {
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      { 
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        { 
          blockcb->onNeighbourPlace(user, newblock,x,y+1,z,user->pos.map,direction);
        } 
      } 
      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user->nick.c_str(), x, y+1, z);
    }

    if (Mineserver::get()->map(user->pos.map)->getBlock(x, y-1, z, &block, &meta) && block != BLOCK_AIR)
    {
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      { 
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        { 
          blockcb->onNeighbourPlace(user, newblock,x,y-1,z,user->pos.map,direction);
        } 
      } 
      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user->nick.c_str(), x, y-1, z);
    }

    if (Mineserver::get()->map(user->pos.map)->getBlock(x, y, z+1, &block, &meta) && block != BLOCK_AIR)
    {
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      { 
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        { 
          blockcb->onNeighbourPlace(user, newblock,x,y,z+1,user->pos.map,direction);
        } 
      } 
      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user->nick.c_str(), x, y, z+1);
    }

    if (Mineserver::get()->map(user->pos.map)->getBlock(x, y, z-1, &block, &meta) && block != BLOCK_AIR)
    {
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      { 
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(newblock))
        { 
          blockcb->onNeighbourPlace(user, newblock,x,y,z-1,user->pos.map,direction);
        } 
      } 
      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user->nick.c_str(), x, y, z-1);
    }
  }
  // Now we're sure we're using it, lets remove from inventory!
  #define INV_TASKBAR_START 36
  if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].getType() == newblock && newblock != -1)
  {
    //if(newblock<256)
    {
      // It's a block
      user->inv[INV_TASKBAR_START+user->currentItemSlot()].decCount();
    }
  }
  #undef INV_TASKBAR_START



  /* TODO: Should be removed from here. Only needed for liquid related blocks? */
  Mineserver::get()->physics(user->pos.map)->checkSurrounding(vec(x, y, z));
  return PACKET_OK;
}
Ejemplo n.º 2
0
int PacketHandler::player_digging(User* user)
{
  int8_t status;
  int32_t x;
  int16_t  y;
  int8_t temp_y;
  int32_t z;
  int8_t direction;
  uint8_t block;
  uint8_t meta;
  BlockBasicPtr blockcb;
  BlockDefault blockD;


  user->buffer >> status >> x >> temp_y >> z >> direction;
  y = (uint8_t)temp_y;

  if (!user->buffer)
  {
    return PACKET_NEED_MORE_DATA;
  }

  user->buffer.removePacket();

  if (!ServerInstance->map(user->pos.map)->getBlock(x, y, z, &block, &meta))
  {
    blockD.revertBlock(user, x, y, z, user->pos.map);
    return PACKET_OK;
  }

  // Blocks that break with first hit
  if (status == BLOCK_STATUS_STARTED_DIGGING &&
      (block == BLOCK_SNOW || block == BLOCK_REED || block == BLOCK_TORCH
    || block == BLOCK_REDSTONE_WIRE || block == BLOCK_RED_ROSE || block == BLOCK_YELLOW_FLOWER 
    || block == BLOCK_BROWN_MUSHROOM || block == BLOCK_RED_MUSHROOM 
    || block == BLOCK_REDSTONE_TORCH_OFF || block == BLOCK_REDSTONE_TORCH_ON))
  {
    status = BLOCK_STATUS_BLOCK_BROKEN;
  }

  switch (status)
  {
  case BLOCK_STATUS_STARTED_DIGGING:
  {
    (static_cast<Hook5<bool, const char*, int32_t, int16_t, int32_t, int8_t>*>(ServerInstance->plugin()->getHook("PlayerDiggingStarted")))->doAll(user->nick.c_str(), x, y, z, direction);

    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
    {
      blockcb = ServerInstance->plugin()->getBlockCB()[i];
      if (blockcb != NULL && blockcb->affectedBlock(block))
      {
        blockcb->onStartedDigging(user, status, x, y, z, user->pos.map, direction);
      }
    }
    break;
  }

  case BLOCK_STATUS_BLOCK_BROKEN:
  {
    //Player tool usage calculation etc

    bool rightUse;
    int16_t itemSlot = user->currentItemSlot() + 36;
    int16_t itemHealth = ServerInstance->inventory()->itemHealth(user->inv[itemSlot].getType(), block, rightUse);
    if (itemHealth > 0)
    {
      user->inv[itemSlot].incHealth();
      if (!rightUse)
      {
        user->inv[itemSlot].incHealth();
      }

      if (itemHealth <= user->inv[itemSlot].getHealth())
      {
        user->inv[itemSlot].decCount();

        if (user->inv[itemSlot].getCount() == 0)
        {
          user->inv[itemSlot].setHealth(0);
          user->inv[itemSlot].setType(-1);
        }
      }
      ServerInstance->inventory()->setSlot(user, WINDOW_PLAYER, itemSlot, user->inv[itemSlot].getType(),
                                              user->inv[itemSlot].getCount(), user->inv[itemSlot].getHealth());
    }

    if ((static_cast<Hook4<bool, const char*, int32_t, int16_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockBreakPre")))->doUntilFalse(user->nick.c_str(), x, y, z))
    {
      blockD.revertBlock(user, x, y, z, user->pos.map);
      return PACKET_OK;
    }

    (static_cast<Hook4<bool, const char*, int32_t, int16_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockBreakPost")))->doAll(user->nick.c_str(), x, y, z);

    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
    {
      blockcb = ServerInstance->plugin()->getBlockCB()[i];
      if (blockcb != NULL && blockcb->affectedBlock(block))
      {
        if (blockcb->onBroken(user, status, x, y, z, user->pos.map, direction))
        {
          // Do not break
          return PACKET_OK;
        }
        else
        {
          break;
        }
      }
    }

    /* notify neighbour blocks of the broken block */
    status = block;
    if (ServerInstance->map(user->pos.map)->getBlock(x + 1, y, z, &block, &meta) && block != BLOCK_AIR)
    {
      (static_cast<Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x + 1, y, z, x, int8_t(y), z);
      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
      {
        blockcb = ServerInstance->plugin()->getBlockCB()[i];
        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))
        {
          blockcb->onNeighbourBroken(user, status, x + 1, y, z, user->pos.map, BLOCK_SOUTH);
        }
      }

    }

    if (ServerInstance->map(user->pos.map)->getBlock(x - 1, y, z, &block, &meta) && block != BLOCK_AIR)
    {
      (static_cast<Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x - 1, y, z, x, int8_t(y), z);
      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
      {
        blockcb = ServerInstance->plugin()->getBlockCB()[i];
        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))
        {
          blockcb->onNeighbourBroken(user, status, x - 1, y, z, user->pos.map, BLOCK_NORTH);
        }
      }

    }

    if (ServerInstance->map(user->pos.map)->getBlock(x, y + 1, z, &block, &meta) && block != BLOCK_AIR)
    {
      (static_cast<Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y + 1, z, x, int8_t(y), z);
      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
      {
        blockcb = ServerInstance->plugin()->getBlockCB()[i];
        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))
        {
          blockcb->onNeighbourBroken(user, status, x, y + 1, z, user->pos.map, BLOCK_TOP);
        }
      }

    }

    if (ServerInstance->map(user->pos.map)->getBlock(x, y - 1, z, &block, &meta) && block != BLOCK_AIR)
    {
      (static_cast<Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y - 1, z, x, int8_t(y), z);
      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
      {
        blockcb = ServerInstance->plugin()->getBlockCB()[i];
        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))
        {
          blockcb->onNeighbourBroken(user, status, x, y - 1, z, user->pos.map, BLOCK_BOTTOM);
        }
      }

    }

    if (ServerInstance->map(user->pos.map)->getBlock(x, y, z + 1, &block, &meta) && block != BLOCK_AIR)
    {
      (static_cast<Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y, z + 1, x, int8_t(y), z);
      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
      {
        blockcb = ServerInstance->plugin()->getBlockCB()[i];
        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))
        {
          blockcb->onNeighbourBroken(user, status, x, y, z + 1, user->pos.map, BLOCK_WEST);
        }
      }

    }

    if (ServerInstance->map(user->pos.map)->getBlock(x, y, z - 1, &block, &meta) && block != BLOCK_AIR)
    {
      (static_cast<Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>*>(ServerInstance->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y, z - 1, x, int8_t(y), z);
      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)
      {
        blockcb = ServerInstance->plugin()->getBlockCB()[i];
        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))
        {
          blockcb->onNeighbourBroken(user, status, x, y, z - 1, user->pos.map, BLOCK_EAST);
        }
      }

    }

    break;
  }
  case BLOCK_STATUS_PICKUP_SPAWN:
  {
    //ToDo: handle
#define itemSlot (36+user->currentItemSlot())
    if (user->inv[itemSlot].getType() > 0)
    {
      ServerInstance->map(user->pos.map)->createPickupSpawn(int(user->pos.x), int(user->pos.y), int(user->pos.z), int(user->inv[itemSlot].getType()), 1, int(user->inv[itemSlot].getHealth()), user);

      user->inv[itemSlot].decCount();
    }
    break;
#undef itemSlot
  }

  }

  return PACKET_OK;
}
Ejemplo n.º 3
0
int PacketHandler::player_digging(User *user)
{
  int8_t status;
  int32_t x;
  int8_t  y;
  int32_t z;
  int8_t direction;
  uint8_t block;
  uint8_t meta;
  BlockBasic* blockcb;
  BlockDefault blockD;


  user->buffer >> status >> x >> y >> z >> direction;

  if(!user->buffer)
  {
    return PACKET_NEED_MORE_DATA;
  }

  user->buffer.removePacket();

  if(!Mineserver::get()->map(user->pos.map)->getBlock(x, y, z, &block, &meta))
  {
    blockD.revertBlock(user,x,y,z,user->pos.map);
    return PACKET_OK;
  }

  switch(status)
  {
    case BLOCK_STATUS_STARTED_DIGGING:
    {
      (static_cast<Hook5<bool,const char*,int32_t,int8_t,int32_t,int8_t>*>(Mineserver::get()->plugin()->getHook("PlayerDiggingStarted")))->doAll(user->nick.c_str(), x, y, z, direction);

      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(block))
        {
          blockcb->onStartedDigging(user, status,x,y,z,user->pos.map,direction);
        }
      }
      break;
    }
    case BLOCK_STATUS_DIGGING:
    {
      (static_cast<Hook5<bool,const char*,int32_t,int8_t,int32_t,int8_t>*>(Mineserver::get()->plugin()->getHook("PlayerDigging")))->doAll(user->nick.c_str(), x, y, z, direction);
      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("PlayerDigging")))->doAll(user->nick.c_str(), x, y, z);
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(block))
        {
          blockcb->onDigging(user, status,x,y,z,user->pos.map,direction);
        }
      }

      break;
    }
/*    case BLOCK_STATUS_STOPPED_DIGGING:
    {
      (static_cast<Hook5<bool,const char*,int32_t,int8_t,int32_t,int8_t>*>(Mineserver::get()->plugin()->getHook("PlayerDiggingStopped")))->doAll(user->nick.c_str(), x, y, z, direction);
      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(block))
        {
          blockcb->onStoppedDigging(user,status, x,y,z,user->pos.map,direction);
        }
      }
      break;
    }*/
    case BLOCK_STATUS_BLOCK_BROKEN:
    {
      //Player tool usage calculation etc
      #define itemSlot (36+user->currentItemSlot())
      bool rightUse;
      int16_t itemHealth=Mineserver::get()->inventory()->itemHealth(user->inv[itemSlot].getType(),block,rightUse);
      if(itemHealth > 0)
      {
         user->inv[itemSlot].incHealth();
         if(!rightUse)
           user->inv[itemSlot].incHealth();
         if(itemHealth <= user->inv[itemSlot].getHealth())
         {
            user->inv[itemSlot].decCount();
            if(user->inv[itemSlot].getCount() == 0)
            {
              user->inv[itemSlot].setHealth(0);
              user->inv[itemSlot].setType(-1);
            }            
         }
         Mineserver::get()->inventory()->setSlot(user,WINDOW_PLAYER,itemSlot,user->inv[itemSlot].getType(),
                                                 user->inv[itemSlot].getCount(),user->inv[itemSlot].getHealth());
      }
      #undef itemSlot

      if ((static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockBreakPre")))->doUntilFalse(user->nick.c_str(), x, y, z))
      {
        blockD.revertBlock(user,x,y,z,user->pos.map);
        return PACKET_OK;
      }

      (static_cast<Hook4<bool,const char*,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockBreakPost")))->doAll(user->nick.c_str(), x, y, z);

      for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
      {
        blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
        if(blockcb!=NULL && blockcb->affectedBlock(block))
        {
          if(blockcb->onBroken(user, status,x,y,z,user->pos.map,direction))
          {
            // Do not break
            blockD.revertBlock(user,x,y,z,user->pos.map);
            return PACKET_OK;
          }
          else
          {
            break;
          }
        }
      }

      /* notify neighbour blocks of the broken block */
      status = block;
      if (Mineserver::get()->map(user->pos.map)->getBlock(x+1, y, z, &block, &meta) && block != BLOCK_AIR)
      {
        (static_cast<Hook7<bool,const char*,int32_t,int8_t,int32_t,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x+1, y, z, x, y, z);
        for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
        {
          blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
          if(blockcb!=NULL && (blockcb->affectedBlock(status)||blockcb->affectedBlock(block)))
          {
            blockcb->onNeighbourBroken(user, status,x+1,y,z,user->pos.map,BLOCK_SOUTH);
          }
        }

      }

      if (Mineserver::get()->map(user->pos.map)->getBlock(x-1, y, z, &block, &meta) && block != BLOCK_AIR)
      {
        (static_cast<Hook7<bool,const char*,int32_t,int8_t,int32_t,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x-1, y, z, x, y, z);
        for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
        {
          blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
          if(blockcb!=NULL && (blockcb->affectedBlock(status)||blockcb->affectedBlock(block)))
          {
            blockcb->onNeighbourBroken(user, status,x-1,y,z,user->pos.map,BLOCK_NORTH);
          }
        }

      }

      if (Mineserver::get()->map(user->pos.map)->getBlock(x, y+1, z, &block, &meta) && block != BLOCK_AIR)
      {
        (static_cast<Hook7<bool,const char*,int32_t,int8_t,int32_t,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y+1, z, x, y, z);
        for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
        {
          blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
          if(blockcb!=NULL && (blockcb->affectedBlock(status)||blockcb->affectedBlock(block)))
          {
            blockcb->onNeighbourBroken(user, status,x,y+1,z,user->pos.map,BLOCK_TOP);
          }
        }

      }

      if (Mineserver::get()->map(user->pos.map)->getBlock(x, y-1, z, &block, &meta) && block != BLOCK_AIR)
      {
        (static_cast<Hook7<bool,const char*,int32_t,int8_t,int32_t,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y-1, z, x, y, z);
        for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
        {
          blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
          if(blockcb!=NULL && (blockcb->affectedBlock(status)||blockcb->affectedBlock(block)))
          {
            blockcb->onNeighbourBroken(user, status,x,y-1,z,user->pos.map,BLOCK_BOTTOM);
          }
        }

      }

      if (Mineserver::get()->map(user->pos.map)->getBlock(x, y, z+1, &block, &meta) && block != BLOCK_AIR)
      {
        (static_cast<Hook7<bool,const char*,int32_t,int8_t,int32_t,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y, z+1, x, y, z);
        for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
        {
          blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
          if(blockcb!=NULL && (blockcb->affectedBlock(status)||blockcb->affectedBlock(block)))
          {
            blockcb->onNeighbourBroken(user, status,x,y,z+1,user->pos.map,BLOCK_WEST);
          }
        }

      }

      if (Mineserver::get()->map(user->pos.map)->getBlock(x, y, z-1, &block, &meta) && block != BLOCK_AIR)
      {
        (static_cast<Hook7<bool,const char*,int32_t,int8_t,int32_t,int32_t,int8_t,int32_t>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourBreak")))->doAll(user->nick.c_str(), x, y, z-1, x, y, z);
        for(uint32_t i =0 ; i<Mineserver::get()->plugin()->getBlockCB().size(); i++)
        {
          blockcb = Mineserver::get()->plugin()->getBlockCB()[i];
          if(blockcb!=NULL && (blockcb->affectedBlock(status)||blockcb->affectedBlock(block)))
          {
            blockcb->onNeighbourBroken(user, status,x,y,z-1,user->pos.map,BLOCK_EAST);
          }
        }

      }

      break;
    }
    case BLOCK_STATUS_PICKUP_SPAWN:
    {
      //ToDo: handle
      #define itemSlot (36+user->currentItemSlot())
      if(user->inv[itemSlot].getType() > 0)
      {
        Mineserver::get()->map(user->pos.map)->createPickupSpawn(user->pos.x, user->pos.y,user->pos.z,user->inv[itemSlot].getType(),1,user->inv[itemSlot].getHealth(),user);

        user->inv[itemSlot].decCount();
      }
      break;
      #undef itemSlot
    }
    
  }

  return PACKET_OK;
}