Esempio n. 1
0
void kit(User *user, std::string command, std::deque<std::string> args)
{
  if(!args.empty())
  {
    std::vector<int> kitItems = Conf::get().vValue("kit_" + args[0]);
    // If kit is found
    if(!kitItems.empty())
    {
      for(uint32 i=0;i<kitItems.size();i++)
      {
        spawnedItem item;
        item.EID     = generateEID();
        item.item    = kitItems[i];
        item.count   = 1;
        item.health=0;
        item.pos.x() = static_cast<int>(user->pos.x*32 + (rand() % 30));
        item.pos.y() = static_cast<int>(user->pos.y*32);
        item.pos.z() = static_cast<int>(user->pos.z*32 + (rand() % 30));
        Map::get().sendPickupSpawn(item);
      }
    }
    else
      reportError(user, "Kit " + args[0] + " not found");
  }
}
Esempio n. 2
0
Mob::Mob()
{
  x = 0;
  y = 0;
  z = 0;
  map = 0;
  yaw = 0;
  pitch = 0;
  meta = 0;
  UID = generateEID();
}
Esempio n. 3
0
void PacketHandler::pickup_spawn(uint8 *data, User *user)
{
  uint32 curpos = 4;
  spawnedItem item;
  item.EID    = generateEID();
  item.health = 0;
  item.item   = getSint16(&data[curpos]);
  curpos     += 2;
  item.count  = data[curpos];
  curpos++;

  item.pos.x()   = getSint32(&data[curpos]);
  curpos        += 4;
  item.pos.y()   = getSint32(&data[curpos]);
  curpos        += 4;
  item.pos.z()   = getSint32(&data[curpos]);
  curpos        += 4;
  item.spawnedBy = user->UID;

  Map::get().sendPickupSpawn(item);
}
Esempio n. 4
0
int PacketHandler::pickup_spawn(User *user)
{
  //uint32_t curpos = 4; //warning: unused variable ‘curpos’
  spawnedItem item;

  item.health = 0;

  int8_t yaw, pitch, roll;

  user->buffer >> (int32_t&)item.EID;

  user->buffer >> (int16_t&)item.item >> (int8_t&)item.count >> (int16_t&)item.health;
  user->buffer >> (int32_t&)item.pos.x() >> (int32_t&)item.pos.y() >> (int32_t&)item.pos.z();
  user->buffer >> yaw >> pitch >> roll;

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

  user->buffer.removePacket();

  item.EID       = generateEID();

  item.spawnedBy = user->UID;
  item.spawnedAt = time(NULL);

  // Modify the position of the dropped item so that it appears in front of user instead of under user
  int distanceToThrow = 64;
  float angle = DEGREES_TO_RADIANS(user->pos.yaw + 45);     // For some reason, yaw seems to be off to the left by 45 degrees from where you're actually looking?
  int x = int(cos(angle) * distanceToThrow - sin(angle) * distanceToThrow);
  int z = int(sin(angle) * distanceToThrow + cos(angle) * distanceToThrow);
  item.pos += vec(x, 0, z);

  Mineserver::get()->map(user->pos.map)->sendPickupSpawn(item);

  return PACKET_OK;
}
Esempio n. 5
0
void ItemProjectile::onRightClick(User* user, Item* item)
{
  int8_t projID = 0;
  switch(item->getType())
  {
    case ITEM_SNOWBALL:
      projID = 61;
    break;
    case ITEM_EGG:
      projID = 62;
    break;
    case ITEM_BOW:
      projID = 60; // TODO check arrows and remove one!
    break;
  }
  if(projID != 0)
  {
    int32_t EID = generateEID();
    Packet pkt;
    //Entity packet (initialization)
    pkt << 0x1E << EID;

    //Spawn snowball on player location
    // 0x17 == add object, 61 == snowball
    pkt << 0x17 << EID << (int8_t)projID << (int32_t)(user->pos.x*32) << (int32_t)((user->pos.y+1.5)*32) << (int32_t)(user->pos.z*32);
  
    float tempMult = 1.f-((user->pos.pitch/90.f)<0?-(user->pos.pitch/90.f):(user->pos.pitch/90.f));
    //Entity velocity 
    pkt << 0x1C << EID << (int16_t)(sinf(-(user->pos.yaw / 360.f) * 2.f*M_PI)*tempMult*32768.f) << (int16_t)(-32768.f*(user->pos.pitch/90.f)) << (int16_t)(cosf(-(user->pos.yaw/ 360.f) * 2.f*M_PI)*tempMult*32768.f);
  
    user->sendAll((uint8_t *)pkt.getWrite(), pkt.getWriteLen());

    item->decCount();
  }
 
}
Esempio n. 6
0
void PacketHandler::player_digging(uint8 *data, User *user)
{
  int curpos  = 0;
  char status = data[curpos];
  curpos++;

  int x = getSint32(&data[curpos]);
  curpos += 4;

  char y = data[curpos];
  curpos++;

  int z = getSint32(&data[curpos]);
  curpos += 4;


  //If block broken
  if(status == BLOCK_STATUS_BLOCK_BROKEN)
  {
    uint8 block; uint8 meta;
    if(Map::get().getBlock(x, y, z, &block, &meta))
    {
      Map::get().sendBlockChange(x, y, z, 0, 0);
      Map::get().setBlock(x, y, z, 0, 0);

      uint8 topblock; uint8 topmeta;
      //Destroy items on top
      if(Map::get().getBlock(x, y+1, z, &topblock, &topmeta) && (topblock == BLOCK_SNOW ||
                                                                 topblock ==
                                                                 BLOCK_BROWN_MUSHROOM ||
                                                                 topblock == BLOCK_RED_MUSHROOM ||
                                                                 topblock == BLOCK_YELLOW_FLOWER ||
                                                                 topblock == BLOCK_RED_ROSE ||
                                                                 topblock == BLOCK_SAPLING))
      {
        Map::get().sendBlockChange(x, y+1, z, 0, 0);
        Map::get().setBlock(x, y+1, z, 0, 0);
        //Others than snow will spawn
        if(topblock != BLOCK_SNOW)
        {
          spawnedItem item;
          item.EID      = generateEID();
          item.health   = 0;
          item.item     = (int)topblock;
          item.count    = 1;

          item.pos.x()  = x*32;
          item.pos.y()  = (y+1)*32;
          item.pos.z()  = z*32;
          //Randomize spawn position a bit
          item.pos.x() += 5+(rand()%22);
          item.pos.z() += 5+(rand()%22);

          Map::get().sendPickupSpawn(item);
        }
      }

      if(block != BLOCK_SNOW && (int)block > 0 && (int)block < 255)
      {
        spawnedItem item;
        item.EID    = generateEID();
        item.health = 0;

        // Spawn drop according to BLOCKDROPS
        // Check propability
        if(BLOCKDROPS.count(block) && BLOCKDROPS[block].probability >= rand()%10000)
        {
          item.item  = BLOCKDROPS[block].item_id;
          item.count = BLOCKDROPS[block].count;
        }
        else
        {
          item.item  = (int)block;
          item.count = 1;
        }
        item.pos.x()  = x*32;
        item.pos.y()  = y*32;
        item.pos.z()  = z*32;
        //Randomize spawn position a bit
        item.pos.x() += 5+(rand()%22);
        item.pos.z() += 5+(rand()%22);

        // If count is greater than 0
        if(item.count > 0)
          Map::get().sendPickupSpawn(item);
      }

      // Check liquid physics
      Physics::get().checkSurrounding(vec(x, y, z));


      // Block physics for BLOCK_GRAVEL and BLOCK_SAND and BLOCK_SNOW
      while(Map::get().getBlock(x, y+1, z, &topblock, &topmeta) && (topblock == BLOCK_GRAVEL ||
                                                                    topblock == BLOCK_SAND ||
                                                                    topblock == BLOCK_SNOW ||
                                                                    topblock ==
                                                                    BLOCK_BROWN_MUSHROOM ||
                                                                    topblock ==
                                                                    BLOCK_RED_MUSHROOM ||
                                                                    topblock ==
                                                                    BLOCK_YELLOW_FLOWER ||
                                                                    topblock == BLOCK_RED_ROSE ||
                                                                    topblock == BLOCK_SAPLING))
      {
        // Destroy original block
        Map::get().sendBlockChange(x, y+1, z, 0, 0);
        Map::get().setBlock(x, y+1, z, 0, 0);

        Map::get().setBlock(x, y, z, topblock, topmeta);
        Map::get().sendBlockChange(x, y, z, topblock, topmeta);

        y++;
      }
    }
  }
}
Esempio n. 7
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;


  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();


  if (!Mineserver::get()->map(user->pos.map)->getBlock(x, y, z, &oldblock, &metadata))
  {
    return PACKET_OK;
  }
  
  // TODO: Handle int16_t itemID's
  /*
  if(newblock > 255 && newblock != ITEM_SIGN)
  {
    return PACKET_OK;
  }
  */
  
  /* Protocol docs say this should be what interacting is. */
  if(oldblock != BLOCK_AIR && newblock == -1)
  {
    (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(int 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))
			{
              return PACKET_OK;
            }
			else
			{
              break;
            }
          }
      }
  }
  bool foundFromInventory = false;

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


  // TODO: Handle processing of
  if(direction == -1 || !foundFromInventory)
  {
    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(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(), check_x, check_y, check_z, oldblock, newblock))
      {
        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))
      {
        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))
    {
      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(int 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)){
          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(int 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(int 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(int 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(int 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(int 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(int 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()].type == newblock && newblock != -1)
  {
    //if(newblock<256)
    {
      // It's a block
      user->inv[INV_TASKBAR_START+user->currentItemSlot()].count--;
      if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].count == 0)
      {
        user->inv[INV_TASKBAR_START+user->currentItemSlot()] = Item();
        //ToDo: add holding change packet.
      }
      user->buffer << (int8_t)PACKET_SET_SLOT << (int8_t)WINDOW_PLAYER
                   << (int16_t)(INV_TASKBAR_START+user->currentItemSlot())
                   << (int16_t)user->inv[INV_TASKBAR_START+user->currentItemSlot()].type;
      if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].type != -1)
      {
        user->buffer << (int8_t)user->inv[INV_TASKBAR_START+user->currentItemSlot()].count
                     << (int16_t)user->inv[INV_TASKBAR_START+user->currentItemSlot()].health;
      }
    }
  }
  #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;
}
Esempio n. 8
0
void giveItems(User *user, std::string command, std::deque<std::string> args)
{
  User *tUser = NULL;
  int itemId = 0, itemCount = 1, itemStacks = 1;

  if(args.size() > 1)
  {
    tUser = getUserByNick(args[0]);

    //First check if item is a number
    itemId = atoi(args[1].c_str());

    //If item was not a number, search the name from config
    if(itemId == 0)
      itemId = Conf::get().iValue(args[1]);

    // Check item validity
    if(!isValidItem(itemId))
    {
      reportError(user, "Item " + args[1] + " not found.");
      return;
    }

    if(args.size() > 2)
    {
      itemCount = atoi(args[2].c_str());
      // If multiple stacks
      itemStacks = roundUpTo(itemCount, 64) / 64; 
      itemCount  -= (itemStacks-1) * 64; 
    }
  }
  else
  {
    reportError(user, "Too few parameters.");
	  return;
  }

  if(tUser)
  {
    int amount = 64;
    for(int i = 0; i < itemStacks; i++)
    {
      // if last stack
      if(i == itemStacks - 1)
        amount = itemCount;

      spawnedItem item;
      item.EID     = generateEID();
      item.item    = itemId;
      item.health  = 0;
      item.count   = amount;
      item.pos.x() = static_cast<int>(tUser->pos.x * 32);
      item.pos.y() = static_cast<int>(tUser->pos.y * 32);
      item.pos.z() = static_cast<int>(tUser->pos.z * 32);

      Map::get().sendPickupSpawn(item);
    }

    Chat::get().sendMsg(user, COLOR_RED + user->nick + " spawned " + args[1], Chat::ADMINS);
  }
  else
    reportError(user, "User " + args[0] + " not found (see /players)");
}
Esempio n. 9
0
int PacketHandler::player_block_placement(User *user)
{
    if(!user->buffer.haveData(12))
    {
        return PACKET_NEED_MORE_DATA;
    }
    sint8 y, direction;
    sint16 newblock;
    sint32 x, z;
    /* replacement of block */
    uint8 oldblock;
    uint8 metadata;
    /* neighbour blocks */
    uint8 block;
    uint8 meta;
    sint8 count,health;

    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();


    if (!Mineserver::get()->map()->getBlock(x, y, z, &oldblock, &metadata))
    {
        return PACKET_OK;
    }

    //Check if we need to open a window
    if(oldblock == BLOCK_CHEST)
    {
        //ToDo: check for large chest!
        Mineserver::get()->inventory()->windowOpen(user,WINDOW_CHEST,x, y, z);
        return PACKET_OK;
    }

    if(oldblock == BLOCK_FURNACE || oldblock == BLOCK_BURNING_FURNACE)
    {
        Mineserver::get()->inventory()->windowOpen(user,WINDOW_FURNACE,x, y, z);
        return PACKET_OK;
    }

    if(oldblock == BLOCK_WORKBENCH)
    {

        Mineserver::get()->inventory()->windowOpen(user,WINDOW_WORKBENCH,x, y, z);
        return PACKET_OK;
    }

    // TODO: Handle sint16 itemID's
    if(newblock > 255 && newblock != ITEM_SIGN)
    {
        return PACKET_OK;
    }

    bool foundFromInventory = false;

#define INV_TASKBAR_START 36
    if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].type == newblock && newblock != -1)
    {
        //Are we really placing this?
        user->inv[INV_TASKBAR_START+user->currentItemSlot()].count--;
        if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].count == 0)
        {
            user->inv[INV_TASKBAR_START+user->currentItemSlot()] = Item();
            //ToDo: add holding change packet.
        }
        user->buffer << (sint8)PACKET_SET_SLOT << (sint8)WINDOW_PLAYER
                     << (sint16)(INV_TASKBAR_START+user->currentItemSlot())
                     << (sint16)user->inv[INV_TASKBAR_START+user->currentItemSlot()].type;
        if(user->inv[INV_TASKBAR_START+user->currentItemSlot()].type != -1)
        {
            user->buffer << (sint8)user->inv[INV_TASKBAR_START+user->currentItemSlot()].count
                         << (sint8)user->inv[INV_TASKBAR_START+user->currentItemSlot()].health;
        }
        foundFromInventory = true;
    }
#undef INV_TASKBAR_START


    // TODO: Handle processing of
    if(direction == -1 || !foundFromInventory)
    {
        return PACKET_OK;
    }

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

        Mineserver::get()->screen()->log("Spawn minecart");
        sint32 EID=generateEID();
        Packet pkt;
        // MINECART
        pkt << PACKET_ADD_OBJECT << (sint32)EID << (sint8)10 << (sint32)(x*32+16) << (sint32)(y*32) << (sint32)(z*32+16);
        user->sendAll((uint8 *)pkt.getWrite(), pkt.getWriteLen());
    }

    if (newblock == -1 && newblock != ITEM_SIGN)
    {
        Mineserver::get()->screen()->log("ignoring: "+dtos(newblock));
        return PACKET_OK;
    }

    if(y < 0)
    {
        return PACKET_OK;
    }


#ifdef _DEBUG
    Mineserver::get()->screen()->log("Block_placement: "+dtos(newblock)+" ("+dtos(x)+","+dtos((int)y)+","+dtos(z)+") dir: "+dtos((int)direction));
#endif

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

    Callback callback;
    Function event;
    Function::invoker_type inv(user, newblock, x, y, z, direction);

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

        /* client doesn't give us the correct block for lava and water, check block above */
        switch(direction)
        {
        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()->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 */
            inv = Function::invoker_type(user, newblock, check_x, check_y, check_z, direction);
            Mineserver::get()->plugin()->runBlockCallback(oldblocktop, "onReplace", inv);
            if ((static_cast<Hook6<bool,User*,sint32,sint8,sint32,uint8,uint8>*>(Mineserver::get()->plugin()->getHook("BlockReplacePre")))->doUntilFalse(user, check_x, check_y, check_z, oldblock, newblock))
            {
                return PACKET_OK;
            }
            (static_cast<Hook6<void,User*,sint32,sint8,sint32,uint8,uint8>*>(Mineserver::get()->plugin()->getHook("BlockReplacePost")))->doAll(user, check_x, check_y, check_z, oldblock, newblock);
        }
        else
        {
            inv = Function::invoker_type(user, newblock, x, y, z, direction);
            Mineserver::get()->plugin()->runBlockCallback(oldblock, "onReplace", inv);
            if ((static_cast<Hook6<bool,User*,sint32,sint8,sint32,uint8,uint8>*>(Mineserver::get()->plugin()->getHook("BlockReplacePre")))->doUntilFalse(user, x, y, z, oldblock, newblock))
            {
                return PACKET_OK;
            }
            (static_cast<Hook6<void,User*,sint32,sint8,sint32,uint8,uint8>*>(Mineserver::get()->plugin()->getHook("BlockReplacePost")))->doAll(user, x, y, z, oldblock, newblock);
        }

        if ((static_cast<Hook5<bool,User*,sint32,sint8,sint32,uint8>*>(Mineserver::get()->plugin()->getHook("BlockPlacePre")))->doUntilFalse(user, x, y, z, newblock))
        {
            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. */
        inv = Function::invoker_type(user, newblock, x, y, z, direction);
        Mineserver::get()->plugin()->runBlockCallback(newblock, "onPlace", inv);

        (static_cast<Hook5<void,User*,sint32,sint8,sint32,uint8>*>(Mineserver::get()->plugin()->getHook("BlockPlacePost")))->doAll(user, x, y, z, newblock);

        /* notify neighbour blocks of the placed block */
        if (Mineserver::get()->map()->getBlock(x+1, y, z, &block, &meta) && block != BLOCK_AIR)
        {
            inv = Function::invoker_type(user, newblock, x+1, y, z, BLOCK_SOUTH);
            Mineserver::get()->plugin()->runBlockCallback(block, "onNeighbourPlace", inv);
            (static_cast<Hook4<void,User*,sint32,sint8,sint32>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user, x+1, y, z);
        }

        if (Mineserver::get()->map()->getBlock(x-1, y, z, &block, &meta) && block != BLOCK_AIR)
        {
            inv = Function::invoker_type(user, newblock, x-1, y, z, BLOCK_NORTH);
            Mineserver::get()->plugin()->runBlockCallback(block, "onNeighbourPlace", inv);
            (static_cast<Hook4<void,User*,sint32,sint8,sint32>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user, x-1, y, z);
        }

        if (Mineserver::get()->map()->getBlock(x, y+1, z, &block, &meta) && block != BLOCK_AIR)
        {
            inv = Function::invoker_type(user, newblock, x, y+1, z, BLOCK_TOP);
            Mineserver::get()->plugin()->runBlockCallback(block, "onNeighbourPlace", inv);
            (static_cast<Hook4<void,User*,sint32,sint8,sint32>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user, x, y+1, z);
        }

        if (Mineserver::get()->map()->getBlock(x, y-1, z, &block, &meta) && block != BLOCK_AIR)
        {
            inv = Function::invoker_type(user, newblock, x, y-1, z, BLOCK_BOTTOM);
            Mineserver::get()->plugin()->runBlockCallback(block, "onNeighbourPlace", inv);
            (static_cast<Hook4<void,User*,sint32,sint8,sint32>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user, x, y-1, z);
        }

        if (Mineserver::get()->map()->getBlock(x, y, z+1, &block, &meta) && block != BLOCK_AIR)
        {
            inv = Function::invoker_type(user, newblock, x, y, z+1, BLOCK_WEST);
            Mineserver::get()->plugin()->runBlockCallback(block, "onNeighbourPlace", inv);
            (static_cast<Hook4<void,User*,sint32,sint8,sint32>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user, x, y, z+1);
        }

        if (Mineserver::get()->map()->getBlock(x, y, z-1, &block, &meta) && block != BLOCK_AIR)
        {
            inv = Function::invoker_type(user, newblock, x, y, z-1, BLOCK_EAST);
            Mineserver::get()->plugin()->runBlockCallback(block, "onNeighbourPlace", inv);
            (static_cast<Hook4<void,User*,sint32,sint8,sint32>*>(Mineserver::get()->plugin()->getHook("BlockNeighbourPlace")))->doAll(user, x, y, z-1);
        }
    }

    /* TODO: Should be removed from here. Only needed for liquid related blocks? */
    Mineserver::get()->physics()->checkSurrounding(vec(x, y, z));
    return PACKET_OK;
}