Exemplo n.º 1
0
int dumpNBT_list(NBT_list *input, uint8 *buffer)
{
    int curpos=0;
    buffer[curpos]=TAG_LIST;
    curpos++;
    curpos+=dumpNBT_string(&buffer[curpos],input->name);

    buffer[curpos]=input->tagId;
    curpos++;

    putSint32(&buffer[curpos],input->length);
    curpos+=4;

    for(int i=0; i<input->length; i++)
    {
        switch(input->tagId)
        {
        case TAG_BYTE:
            buffer[curpos]=*(char *)input->items[i];
            curpos++;
            break;
        case TAG_SHORT:
            putSint16(&buffer[curpos], *(int *)input->items[i]);
            curpos+=2;
            break;
        case TAG_INT:
            putSint32(&buffer[curpos], *(int *)input->items[i]);
            curpos+=4;
            break;
        case TAG_LONG:
            putSint64(&buffer[curpos], *(long long *)input->items[i]);
            curpos+=8;
            break;
        case TAG_FLOAT:
            putFloat(&buffer[curpos], *(float *)input->items[i]);
            curpos+=4;
            break;
        case TAG_DOUBLE:
            putDouble(&buffer[curpos], *(double *)input->items[i]);
            curpos+=8;
            break;
        case TAG_STRING:
            curpos+=dumpNBT_string(&buffer[curpos],*(std::string *)input->items[i]);
            break;
        case TAG_BYTE_ARRAY:
            curpos+=dumpNBT_byte_array((NBT_byte_array *)input->items[i], &buffer[curpos],true);
            break;
        case TAG_COMPOUND:
            curpos+=dumpNBT_struct((NBT_struct *)input->items[i], &buffer[curpos],true);
            break;
        }
    }

    return curpos;
}
Exemplo n.º 2
0
void PacketHandler::holding_change(uint8 *data, User *user)
{
  int itemID = getUint16(&data[4]);

  //Send holding change to others
  uint8 holdingPackage[7];
  holdingPackage[0] = 0x10;
  putSint32(&holdingPackage[1], user->UID);
  putSint16(&holdingPackage[5], itemID);
  user->sendOthers(&holdingPackage[0], 7);

}
Exemplo n.º 3
0
int dumpNBT_string(uint8 *buffer, std::string name)
{
    int curpos=0;
    putSint16(buffer, name.length());
    curpos+=2;

    for(unsigned int i=0; i<name.length(); i++)
    {
        buffer[curpos]=name[i];
        curpos++;
    }

    return curpos;
}
Exemplo n.º 4
0
int dumpNBT_value(NBT_value *input, uint8 *buffer)
{
    int curpos=0;
    buffer[curpos]=input->type;
    curpos++;
    curpos+=dumpNBT_string(&buffer[curpos],input->name);

    switch(input->type)
    {
    case TAG_BYTE:
        buffer[curpos]=*(char *)input->value;
        curpos++;
        break;
    case TAG_SHORT:
        putSint16(&buffer[curpos], *(int *)input->value);
        curpos+=2;
        break;
    case TAG_INT:
        putSint32(&buffer[curpos], *(int *)input->value);
        curpos+=4;
        break;
    case TAG_LONG:
        putSint64(&buffer[curpos], *(long long *)input->value);
        curpos+=8;
        break;
    case TAG_FLOAT:
        putFloat(&buffer[curpos], *(float *)input->value);
        curpos+=4;
        break;
    case TAG_DOUBLE:
        putDouble(&buffer[curpos], *(double *)input->value);
        curpos+=8;
        break;
    case TAG_STRING:
        curpos+=dumpNBT_string(&buffer[curpos],*(std::string *)input->value);
        break;
    }

    return curpos;
}
Exemplo n.º 5
0
void Map::posToId(int x, int z, uint32 *id)
{
  uint8 *id_pointer = reinterpret_cast<uint8 *>(id);
  putSint16(&id_pointer[0], x);
  putSint16(&id_pointer[2], z);
}
Exemplo n.º 6
0
void NBT_Value::Write(std::vector<uint8> &buffer)
{
  int storeAt = buffer.size();;
  switch(m_type)
  {
  case TAG_BYTE:
    buffer.push_back(m_value.byteVal);
    break;
  case TAG_SHORT:
    buffer.resize(storeAt + 2);
    putSint16(&buffer[storeAt], m_value.shortVal);
    break;
  case TAG_INT:
    buffer.resize(storeAt + 4);
    putSint32(&buffer[storeAt], m_value.intVal);
    break;
  case TAG_LONG:
    buffer.resize(storeAt + 8);
    putSint64(&buffer[storeAt], m_value.longVal);
    break;
  case TAG_FLOAT:
    buffer.resize(storeAt + 4);
    putFloat(&buffer[storeAt], m_value.floatVal);
    break;
  case TAG_DOUBLE:
    buffer.resize(storeAt + 8);
    putDouble(&buffer[storeAt], m_value.doubleVal);
    break;
  case TAG_BYTE_ARRAY:
    {
      int arraySize = m_value.byteArrayVal ? m_value.byteArrayVal->size() : 0;
      buffer.resize(storeAt + 4 + arraySize);
      putSint32(&buffer[storeAt], arraySize);
      storeAt += 4;
      if(arraySize)
        memcpy(&buffer[storeAt], &(*m_value.byteArrayVal)[0], arraySize);
      break;
    }
  case TAG_STRING:
    {
      int stringLen = m_value.stringVal ? m_value.stringVal->size() : 0;
      buffer.resize(storeAt + 2 + stringLen);
      putSint16(&buffer[storeAt], (sint16)stringLen);
      storeAt += 2;
      if(stringLen>0)
        memcpy(&buffer[storeAt], m_value.stringVal->c_str(), stringLen);
      break;
    }
  case TAG_LIST:
    {
      buffer.resize(storeAt + 5);
      int listCount = m_value.listVal.data ? m_value.listVal.data->size() : 0;
      buffer[storeAt] = m_value.listVal.type;
      storeAt++;
      putSint32(&buffer[storeAt], listCount);
      for(int i=0;i<listCount;i++)
        (*m_value.listVal.data)[i]->Write(buffer);
      break;
    }
  case TAG_COMPOUND:
    {
      int compoundCount = m_value.compoundVal ? m_value.compoundVal->size() : 0;
      if(compoundCount)
      {
        std::map<std::string, NBT_Value*>::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end();
        for( ; iter != end; iter++)
        {
          const std::string &key = iter->first;
          int keySize = key.size();
          NBT_Value *val = iter->second;
          int curPos = buffer.size();
          buffer.resize(curPos + 3 + keySize);
          buffer[curPos] = (uint8)val->GetType();
          curPos++;
          putSint16(&buffer[curPos], keySize);
          curPos += 2;
          if(keySize)
            memcpy(&buffer[curPos], key.c_str(), keySize);
          val->Write(buffer);
        }
      }
      buffer.push_back(TAG_END);
      break;
    }
  case TAG_END:
    break; //for completeness
  }
}
Exemplo n.º 7
0
int PacketHandler::complex_entities(User *user)
{
  if(user->buffer.size() < 12)
    return PACKET_NEED_MORE_DATA;

  int curpos = 0;
  unsigned int i;
  uint8 intArray[4];
  uint8 shortArray[2];

  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+4, intArray);
  int x = getSint32(&intArray[0]);
  curpos += 4;
  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+2, shortArray);
  int y = getSint16(&shortArray[0]);
  curpos += 2;
  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+4, intArray);
  int z = getSint32(&intArray[0]);
  curpos += 4;

  std::copy(user->buffer.begin()+curpos, user->buffer.begin()+curpos+2, shortArray);
  int len = getSint16(&shortArray[0]);
  curpos += 2;

  // Wait for whole message
  if(user->buffer.size() < (unsigned int)curpos+len)
    return PACKET_NEED_MORE_DATA;

  //ToDo: check len
  uint8 *buffer = new uint8[len];
  for(i = 0; i < (uint32)len; i++)
  {
    buffer[i] = user->buffer[curpos+i];
  }
  curpos += len;

  user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos);

  uint8 block, meta;
  Map::get().getBlock(x, y, z, &block, &meta);

  //We only handle chest for now
  if(block != BLOCK_CHEST)
  {
    delete[] buffer;
    return curpos;
  }


  //Calculate uncompressed size and allocate memory
  uLongf uncompressedSize   = ALLOCATE_NBTFILE; //buffer[len-3] + (buffer[len-2]<<8) + (buffer[len-1]<<16) + (buffer[len]<<24);
  uint8 *uncompressedBuffer = new uint8[uncompressedSize];
  
  //Initialize zstream to handle gzip format
  z_stream zstream;
  zstream.zalloc    = (alloc_func)0;
  zstream.zfree     = (free_func)0;
  zstream.opaque    = (voidpf)0;
  zstream.next_in   = buffer;
  zstream.next_out  = uncompressedBuffer;
  zstream.avail_in  = len;
  zstream.avail_out = uncompressedSize;
  zstream.total_in  = 0;
  zstream.total_out = 0;
  zstream.data_type = Z_BINARY;
  inflateInit2(&zstream, 1+MAX_WBITS);
  //Uncompress
  if(/*int state=*/inflate(&zstream, Z_FULL_FLUSH)!=Z_OK)
  {
      inflateEnd(&zstream);
  }
  //Get size
  uncompressedSize  = zstream.total_out;
  
  //Push data to NBT struct
  NBT_struct newObject;
  TAG_Compound(uncompressedBuffer, &newObject, true);

  //These are not needed anymore
  delete[] buffer;
  delete[] uncompressedBuffer;

  //Get chunk position
  int block_x = blockToChunk(x);
  int block_z = blockToChunk(z);
  uint32 chunkID;

  NBT_struct *theEntity = 0;


  //Load map
  if(Map::get().loadMap(block_x, block_z))
  {
    Map::get().posToId(block_x, block_z, &chunkID);
    NBT_struct mapData = Map::get().maps[chunkID];

    //Try to find entitylist from the chunk
    NBT_list *entitylist = get_NBT_list(&mapData, "TileEntities");

    //If list exists
    if(entitylist)
    {
      //Verify list type
      if(entitylist->tagId != TAG_COMPOUND)
      {
        //If wrong type, recreate
        freeNBT_list(entitylist);
        for(i = 0; i < mapData.lists.size(); i++)
        {
          if(mapData.lists[i].name == "TileEntities")
          {
            //Destroy old list
            freeNBT_list(&mapData.lists[i]);
            mapData.lists.erase(mapData.lists.begin()+i);
            break;
          }
        }
        
        //New list
        NBT_list newlisting;  
        newlisting.name   = "TileEntities";
        newlisting.tagId  = TAG_COMPOUND;
        newlisting.length = 0;
        mapData.lists.push_back(newlisting);

        entitylist = get_NBT_list(&mapData, "TileEntities");
      }

      NBT_struct **entities = (NBT_struct **)entitylist->items;
      bool entityExists     = false;
      int existingID        = -1;

      //Search for mathing entity in the list
      for(int i = 0; i < entitylist->length; i++)
      {
        NBT_struct *entity = entities[i];
        std::string id;

        //Get ID
        if(get_NBT_value(entity, "id", &id))
        {
          int entity_x, entity_y, entity_z;
          if(!get_NBT_value(entity, "x", &entity_x) ||
             !get_NBT_value(entity, "y", &entity_y) ||
             !get_NBT_value(entity, "z", &entity_z))
          {
            continue;
          }

          //Check for mathing blocktype and ID
          if(block == BLOCK_CHEST && id == "Chest")
          {
            if(x == entity_x && y == entity_y && z == entity_z)
            {
              entityExists = true;
              theEntity    = entity;
              existingID   = i;
              break;
            }
          }
        }
      } //End For entitylist

      //Generate struct
      theEntity = new NBT_struct;
      NBT_value value;

      //Push ID
      value.type  = TAG_STRING;
      value.name  = "id";
      std::string *name =  new std::string;
      value.value = (void *)name;
      *(std::string *)value.value = "Chest";
      theEntity->values.push_back(value);

      //Position
      value.type  = TAG_INT;
      value.name  = "x";
      value.value = (void *)new int;
      *(int *)value.value = x;
      theEntity->values.push_back(value);

      value.name  = "y";
      value.value = (void *)new int;
      *(int *)value.value = y;
      theEntity->values.push_back(value);

      value.name  = "z";
      value.value = (void *)new int;
      *(int *)value.value = z;
      theEntity->values.push_back(value);

      //Put special chest items
      if(block == BLOCK_CHEST)
      {
        NBT_list *newlist = get_NBT_list(&newObject, "Items");
        if(!newlist)
        {
          //std::cout << "Items not found!" << std::endl;
          return curpos;
        }
        NBT_list itemlist;
        itemlist.name   = "Items";
        itemlist.tagId  = TAG_COMPOUND;
        itemlist.length = newlist->length;
        itemlist.items  = (void **)new NBT_struct *[itemlist.length];

        NBT_struct **structlist = (NBT_struct **)itemlist.items;
        for(int i = 0; i < itemlist.length; i++)
        {
          structlist[i]        = new NBT_struct;
          char type_char;
          sint16 type_sint16;

          //Generate struct
          value.type             = TAG_BYTE;
          value.name             = "Count";          
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Count", &type_char);
          value.value            = (void *)new char;
          *(char *)value.value   = type_char;
          structlist[i]->values.push_back(value);

          value.type             = TAG_BYTE;
          value.name             = "Slot";
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Slot", &type_char);
          value.value            = (void *)new char;
          *(char *)value.value   = type_char;
          structlist[i]->values.push_back(value);

          value.type             = TAG_SHORT;
          value.name             = "Damage";          
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "Damage", &type_sint16);
          value.value            = (void *)new sint16;
          *(sint16 *)value.value = type_sint16;
          structlist[i]->values.push_back(value);

          value.type             = TAG_SHORT;
          value.name             = "id";
          get_NBT_value((NBT_struct *)((NBT_struct **)newlist->items)[i], "id", &type_sint16);
          value.value            = (void *)new sint16;
          *(sint16 *)value.value = type_sint16;
          structlist[i]->values.push_back(value);
        }

        theEntity->lists.push_back(itemlist);
      }
      
      //If entity doesn't exist in the list, resize the list to fit it in
      if(!entityExists)
      {
        
        //ToDo: try this!
        NBT_struct **newlist = new NBT_struct *[entitylist->length+1];
        NBT_struct **oldlist = (NBT_struct **)entitylist->items;
        uint8 *structbuffer  = new uint8[ALLOCATE_NBTFILE];        
        for(int i = 0; i < entitylist->length; i++)
        {
          newlist[i] = new NBT_struct;
          dumpNBT_struct(oldlist[i],structbuffer);
          TAG_Compound(structbuffer, newlist[i],true);
          freeNBT_struct(oldlist[i]);
          oldlist[i] = NULL;
        }
        
        delete [] structbuffer;
        entitylist->length++;
        entitylist->items = (void **)newlist;
        delete [] (NBT_struct **)oldlist;
        newlist[entitylist->length-1] = theEntity;
        
      }
      //If item exists, replace the old with the new
      else
      {
        //Destroy old entitylist
        NBT_struct **oldlist = (NBT_struct **)entitylist->items;
        freeNBT_struct(oldlist[existingID]);
        //Replace with the new
        oldlist[existingID]  = theEntity;
      }

      //Mark chunk as changed
      Map::get().mapChanged[chunkID] = true;
      
    } //If entity exists
  } //If loaded map

  //Send complex entity packet to others
  if(theEntity)
  {
    uint8 *structdump = new uint8[ALLOCATE_NBTFILE];
    uint8 *packetData = new uint8[ALLOCATE_NBTFILE];
    int dumped        = dumpNBT_struct(theEntity, structdump);
    uLongf written    = ALLOCATE_NBTFILE;

    z_stream zstream2;
    zstream2.zalloc    = Z_NULL;
    zstream2.zfree     = Z_NULL;
    zstream2.opaque    = Z_NULL;
    zstream2.next_out  = &packetData[13];
    zstream2.next_in   = structdump;
    zstream2.avail_in  = dumped;
    zstream2.avail_out = written;
    zstream2.total_out = 0;
    zstream2.total_in  = 0;
    deflateInit2(&zstream2, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15+MAX_WBITS, 8,
                 Z_DEFAULT_STRATEGY);

    if(int state=deflate(&zstream2,Z_FULL_FLUSH)!=Z_OK)
    {
      std::cout << "Error in deflate: " << state << std::endl;
      deflateEnd(&zstream2);
    }
    else
    {
      written = zstream2.total_out;
      packetData[0] = 0x3b; //Complex Entities
      putSint32(&packetData[1],x);
      putSint16(&packetData[5],y);
      putSint32(&packetData[7],z);
      putSint16(&packetData[11], (sint16)written);
      user->sendAll((uint8 *)&packetData[0], 13+written);
    }

    delete [] packetData;
    delete [] structdump;
  }





  return curpos;
}
Exemplo n.º 8
0
// Login request (http://mc.kev009.com/wiki/Protocol#Login_Request_.280x01.29)
int PacketHandler::login_request(User *user)
{
  //Check that we have enought data in the buffer
  if(user->buffer.size() < 12)
    return PACKET_NEED_MORE_DATA;

  uint32 curpos = 0;
  int i;

  //Client protocol version
  uint8 tmpIntArray[4] = {0};
  for(i = 0; i < 4; i++)
    tmpIntArray[i] = user->buffer[curpos+i];
  int version = getUint32(&tmpIntArray[0]);
  curpos += 4;

  //Player name length
  uint8 tmpShortArray[2] = {0};
  for(i = 0; i < 2; i++)
    tmpShortArray[i] = user->buffer[curpos+i];
  int len = getUint16(&tmpShortArray[0]);
  curpos += 2;

  //Check for data
  if(user->buffer.size() < curpos+len+2)
    return PACKET_NEED_MORE_DATA;


  std::string player;
  //Read player name
  for(int pos = 0; pos < len; pos++)
  {
    player += user->buffer[curpos+pos];
  }
  curpos += len;


  //Password length
  for(i = 0; i < 2; i++)
    tmpShortArray[i] = user->buffer[curpos+i];
  len     = getUint16(&tmpShortArray[0]);
  curpos += 2;

  std::string passwd;
  //Check for data
  if(user->buffer.size() < curpos+len)
    return PACKET_NEED_MORE_DATA;


  //Read password
  for(int pos = 0; pos < len; pos++)
  {
    passwd += user->buffer[curpos+pos];
  }
  curpos += len;

  //Package completely received, remove from buffer
  user->buffer.erase(user->buffer.begin(), user->buffer.begin()+curpos);

  std::cout << "Player " << user->UID << " login v." << version <<" : " << player <<":"<<
  passwd << std::endl;

  // If version is not 2 or 3
  if(version != 4 && version != 3 && version != 2)
  {
    user->kick(Conf::get().sValue("wrong_protocol_message"));
    return curpos;
  }

  // If userlimit is reached
  if((int)Users.size() >= Conf::get().iValue("userlimit"))
  {
    user->kick(Conf::get().sValue("server_full_message"));
    return curpos;
  }

  user->changeNick(player);

  //Load user data
  user->loadData();

  //Login OK package
  char data[9] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  putSint32((uint8 *)&data[1], user->UID);
  bufferevent_write(user->buf_ev, (char *)&data[0], 9);

  //Send server time (after dawn)
  uint8 data3[9] = {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00};
  bufferevent_write(user->buf_ev, (char *)&data3[0], 9);

  //Inventory
  uint8 data4[7+36*5];
  data4[0] = 0x05;
  putSint32(&data4[1], -1);
  data4[5] = 0;
  data4[6] = 36;
  int curpos2 = 7;
  //Send main inventory
  for(i = 0; i < 36; i++)
  {
    if(user->inv.main[i].count)
    {
      putSint16(&data4[curpos2], user->inv.main[i].type);     //Type
      curpos2       += 2;
      data4[curpos2] = user->inv.main[i].count;               //Count
      curpos2++;
      putSint16(&data4[curpos2], user->inv.main[i].health); //Health
      curpos2 += 2;
    }
    else
    {
      //Empty slot
      putSint16(&data4[curpos2], -1);
      curpos2 += 2;
    }
  }
  bufferevent_write(user->buf_ev, (char *)&data4[0], curpos2);


  //Send equipped inventory
  putSint32(&data4[1], -3);
  data4[6] = 4;
  curpos2  = 7;
  for(i = 0; i < 4; i++)
  {
    if(user->inv.equipped[i].count)
    {
      putSint16(&data4[curpos2], user->inv.equipped[i].type);     //Type
      curpos2       += 2;
      data4[curpos2] = user->inv.equipped[i].count;               //Count
      curpos2++;
      putSint16(&data4[curpos2], user->inv.equipped[i].health); //Health
      curpos2 += 2;
    }
    else
    {
      //Empty slot
      putSint16(&data4[curpos2], -1);
      curpos2 += 2;
    }
  }
  bufferevent_write(user->buf_ev, (char *)&data4[0], curpos2);

  //Send crafting inventory
  putSint32(&data4[1], -2);
  data4[6] = 4;
  curpos2  = 7;
  for(i = 0; i < 4; i++)
  {
    if(user->inv.crafting[i].count)
    {
      putSint16(&data4[curpos2], user->inv.crafting[i].type);     //Type
      curpos2       += 2;
      data4[curpos2] = user->inv.crafting[i].count;               //Count
      curpos2++;
      putSint16(&data4[curpos2], user->inv.crafting[i].health); //Health
      curpos2 += 2;
    }
    else
    {
      //Empty slot
      putSint16(&data4[curpos2], -1);
      curpos2 += 2;
    }
  }
  bufferevent_write(user->buf_ev, (char *)&data4[0], curpos2);

  // Send motd
  std::ifstream motdfs( MOTDFILE.c_str());

  std::string temp;

  while(getline( motdfs, temp ))
  {
    // If not commentline
    if(temp[0] != COMMENTPREFIX)
      Chat::get().sendMsg(user, temp, Chat::USER);
  }
  motdfs.close();

  //Teleport player
  user->teleport(user->pos.x, user->pos.y+2, user->pos.z);

  //Put nearby chunks to queue
  for(int x = -user->viewDistance; x <= user->viewDistance; x++)
  {
    for(int z = -user->viewDistance; z <= user->viewDistance; z++)
    {
      user->addQueue((sint32)user->pos.x/16+x, (sint32)user->pos.z/16+z);
    }
  }
  // Push chunks to user
  user->pushMap();

  //Spawn this user to others
  user->spawnUser((sint32)user->pos.x*32, ((sint32)user->pos.y+2)*32, (sint32)user->pos.z*32);
  //Spawn other users for connected user
  user->spawnOthers();


  //Send "On Ground" signal
  char data6[2] = {0x0A, 0x01};
  bufferevent_write(user->buf_ev, (char *)&data6[0], 2);

  user->logged = true;

  Chat::get().sendMsg(user, player+" connected!", Chat::ALL);

  return curpos;
}
Exemplo n.º 9
0
bool User::updatePos(double x, double y, double z, double stance)
{
  if(nick.size() && logged)
  {
    //Do we send relative or absolute move values
    if(0)  //abs(x-this->pos.x)<127
           //&& abs(y-this->pos.y)<127
           //&& abs(z-this->pos.z)<127)
    {
      uint8 movedata[8];
      movedata[0] = 0x1f; //Relative move
      putSint32(&movedata[1], (sint32)this->UID);
      movedata[5] = (char)(x-this->pos.x);
      movedata[6] = (char)(y-this->pos.y);
      movedata[7] = (char)(z-this->pos.z);
      this->sendOthers(&movedata[0], 8);
    }
    else
    {
      this->pos.x      = x;
      this->pos.y      = y;
      this->pos.z      = z;
      this->pos.stance = stance;
      uint8 teleportData[19];
      teleportData[0]  = 0x22; //Teleport
      putSint32(&teleportData[1], this->UID);
      putSint32(&teleportData[5], (int)(this->pos.x*32));
      putSint32(&teleportData[9], (int)(this->pos.y*32));
      putSint32(&teleportData[13], (int)(this->pos.z*32));
      teleportData[17] = (char)this->pos.yaw;
      teleportData[18] = (char)this->pos.pitch;
      this->sendOthers(&teleportData[0], 19);
    }

    //Check if there are items in this chunk!
    sint32 chunk_x = blockToChunk((sint32)x);
    sint32 chunk_z = blockToChunk((sint32)z);
    uint32 chunkHash;
    Map::get().posToId(chunk_x, chunk_z, &chunkHash);
    if(Map::get().mapItems.count(chunkHash))
    {
      //Loop through items and check if they are close enought to be picked up
      for(sint32 i = Map::get().mapItems[chunkHash].size()-1; i >= 0; i--)
      {
        //No more than 2 blocks away
        if(abs((sint32)x-Map::get().mapItems[chunkHash][i]->pos.x()/32) < 2 &&
           abs((sint32)z-Map::get().mapItems[chunkHash][i]->pos.z()/32) < 2 &&
           abs((sint32)y-Map::get().mapItems[chunkHash][i]->pos.y()/32) < 2)
        {
          //Dont pickup own spawns right away
          if(Map::get().mapItems[chunkHash][i]->spawnedBy != this->UID ||
             Map::get().mapItems[chunkHash][i]->spawnedAt+2 < time(0))
          {
            //Check player inventory for space!
            if(checkInventory(Map::get().mapItems[chunkHash][i]->item,
                              Map::get().mapItems[chunkHash][i]->count))
            {
              //Send player collect item packet
              uint8 *packet = new uint8[9];
              packet[0] = PACKET_COLLECT_ITEM;
              putSint32(&packet[1], Map::get().mapItems[chunkHash][i]->EID);
              putSint32(&packet[5], this->UID);
        buffer.addToWrite(packet, 9);

              //Send everyone destroy_entity-packet
              packet[0] = PACKET_DESTROY_ENTITY;
              putSint32(&packet[1], Map::get().mapItems[chunkHash][i]->EID);
              //ToDo: Only send users in range
              this->sendAll(packet, 5);

              packet[0] = PACKET_ADD_TO_INVENTORY;
              putSint16(&packet[1], Map::get().mapItems[chunkHash][i]->item);
              packet[3] = Map::get().mapItems[chunkHash][i]->count;
              putSint16(&packet[4], Map::get().mapItems[chunkHash][i]->health);

        buffer.addToWrite(packet, 6);

              //We're done, release packet memory
              delete[] packet;


              Map::get().items.erase(Map::get().mapItems[chunkHash][i]->EID);
              delete Map::get().mapItems[chunkHash][i];
              Map::get().mapItems[chunkHash].erase(Map::get().mapItems[chunkHash].begin()+i);
            }
          }
        }
      }
    }


    //Chunk position changed, check for map updates
    if((int)(x/16) != curChunk.x() || (int)(z/16) != curChunk.z())
    {
      //This is not accurate chunk!!
      curChunk.x() = (int)(x/16);
      curChunk.z() = (int)(z/16);

      for(int mapx = -viewDistance+curChunk.x(); mapx <= viewDistance+curChunk.x(); mapx++)
      {
        for(int mapz = -viewDistance+curChunk.z(); mapz <= viewDistance+curChunk.z(); mapz++)
        {
          addQueue(mapx, mapz);
        }
      }

      for(unsigned int i = 0; i < mapKnown.size(); i++)
      {
        //If client has map data more than viesDistance+1 chunks away, remove it
        if(mapKnown[i].x() < curChunk.x()-viewDistance-1 ||
           mapKnown[i].x() > curChunk.x()+viewDistance+1 ||
           mapKnown[i].z() < curChunk.z()-viewDistance-1 ||
           mapKnown[i].z() > curChunk.z()+viewDistance+1)
          addRemoveQueue(mapKnown[i].x(), mapKnown[i].z());
      }
    }
  }

  this->pos.x      = x;
  this->pos.y      = y;
  this->pos.z      = z;
  this->pos.stance = stance;
  return true;
}