Пример #1
0
    static bool HandleGMFlyCommand(ChatHandler* handler, const char* args)
    {
        if (!*args)
            return false;

        Player *target =  handler->getSelectedPlayer();
        if (!target)
            target = handler->GetSession()->GetPlayer();

        WorldPacket data;
        if (strncmp(args, "on", 3) == 0)
            data.SetOpcode(UNKNOWN_OPCODE);
        else if (strncmp(args, "off", 4) == 0)
            data.SetOpcode(UNKNOWN_OPCODE);
        else
        {
            handler->SendSysMessage(LANG_USE_BOL);
            return false;
        }
        data.append(target->GetPackGUID());
        data << uint32(0);                                      // unknown
        target->SendMessageToSet(&data, true);
        handler->PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, handler->GetNameLink(target).c_str(), args);
        return true;
    }
Пример #2
0
void Pet::SendNullSpellsToOwner()
{
    WorldPacket data;
    data.SetOpcode(SMSG_PET_SPELLS);
    data << uint64(0);
    m_Owner->GetSession()->SendPacket(&data);
}
Пример #3
0
void WorldSocket::OutPacket(uint16 opcode, size_t len, const void* data)
{
	OUTPACKET_RESULT res;
	if( (len + 10) > WORLDSOCKET_SENDBUF_SIZE )
	{
		printf("WARNING: Tried to send a packet of %u bytes (which is too large) to a socket. Opcode was: %u (0x%03X)\n", (unsigned int)len, (unsigned int)opcode, (unsigned int)opcode);
		return;
	}

	res = _OutPacket(opcode, len, data);
	if(res == OUTPACKET_RESULT_SUCCESS)
		return;

	if(res == OUTPACKET_RESULT_NO_ROOM_IN_BUFFER)
	{
		/* queue the packet */
		queueLock.Acquire();
		//WorldPacket * pck = new WorldPacket(opcode, len);
		WorldPacket * pck = g_bufferPool.Allocate(len);
		pck->SetOpcode(opcode);
		if(len) pck->append((const uint8*)data, len);
		_queue.Push(pck);
		queueLock.Release();
	}
}
Пример #4
0
void CGroup::PackGroupMemberInfo(uint32_t userid, WorldPacket &info)
{
	info.SetOpcode(CMD_SC_GROUP_MEMBER_INFO);
	std::map<uint32_t, SGroupMember>::iterator it = m_mapUserGroup.find(userid);
	std::map<uint32_t, uint8_t>::iterator itmission;
	if (it != m_mapUserGroup.end())
	{
		info << (it->second).dwUserId;
		info << (it->second).dwCredit;
		info << (it->second).byPosion;	

		info << (uint32_t)(it->second).mapMission.size();
		for (itmission = (it->second).mapMission.begin(); itmission != (it->second).mapMission.end(); itmission++)
		{
			info << itmission->first;
			info << itmission->second;
		}

		info << (it->second).dwCreditSupport;
	}
	else
	{
		info << (uint32_t) 0;
		info << (uint32_t) 0;
		info << (uint8_t) 0;

		info << (uint32_t) 0;

		info << (uint32_t) 0;
	}
}	
Пример #5
0
void SubGroup::Disband(bool bRemoveGroup)
{
	WorldPacket data;
	data.SetOpcode(SMSG_GROUP_DESTROYED);

	WorldPacket data2;
	data2.SetOpcode(SMSG_PARTY_COMMAND_RESULT);
	data2 << uint32(2) << uint8(0) << uint32(0);	// you leave the group

	GroupMembersSet::iterator itr = m_GroupMembers.begin();
	for(; itr != m_GroupMembers.end(); ++itr)
	{
		(*itr)->GetSession()->SendPacket(&data);
		(*itr)->GetSession()->SendPacket(&data2);
		(*itr)->SetSubGroup(0);
		m_Parent->m_MemberCount--;

		if(bRemoveGroup)
		{
			(*itr)->SetGroup(NULL);
			m_Parent->SendNullUpdate((*itr));
		}
		/* remove SoulStones if caster and reciever are not the same player */
		if((*itr)->SoulStoneReciever && (*itr)->SoulStoneReciever!=(*itr)->GetGUID())
			(*itr)->removeSoulStone();
	}

	m_Parent->m_SubGroups[m_Id] = NULL;
	delete this;
}
Пример #6
0
void CGroup::PackGroupInfo(WorldPacket &pkg)
{
	std::vector<unsigned char> vecEnums;
	vecEnums.push_back(E_GROUP_dwId);
	vecEnums.push_back(E_GROUP_strName);
	vecEnums.push_back(E_GROUP_dwCreateId);
	vecEnums.push_back(E_GROUP_strCreateName);
	vecEnums.push_back(E_GROUP_dwCredit);
	vecEnums.push_back(E_GROUP_wLevel);
	vecEnums.push_back(E_GROUP_wPersionLimit);
	vecEnums.push_back(E_GROUP_byPosion1Limit);
	vecEnums.push_back(E_GROUP_byPosion2Limit);
	vecEnums.push_back(E_GROUP_byPosion3Limit);
	vecEnums.push_back(E_GROUP_byPosion4Limit);
	vecEnums.push_back(E_GROUP_vecPosion1Persion);
	vecEnums.push_back(E_GROUP_vecPosion1PersionStr);
	vecEnums.push_back(E_GROUP_vecPosion2Persion);
	vecEnums.push_back(E_GROUP_vecPosion3Persion);
	vecEnums.push_back(E_GROUP_vecPosion4Persion);
	vecEnums.push_back(E_GROUP_vecPosion5Persion);
	vecEnums.push_back(E_GROUP_wPersionNumber);
	vecEnums.push_back(E_GROUP_strNotice);
	vecEnums.push_back(E_GROUP_dwNeedCredit);
	vecEnums.push_back(E_GROUP_dwCreditLimit);
	vecEnums.push_back(E_GROUP_dwMissionFlushTime);
	vecEnums.push_back(E_GROUP_byMissionFlushNumber);
	vecEnums.push_back(E_GROUP_dwMissionFlushPoint);

	pkg.SetOpcode(CMD_SC_GROUP_INFO);
	saveDataNeed(pkg, vecEnums);
	clearDirtyFlag();
}
Пример #7
0
    void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data)
    {
        MoveSplineFlag splineflags = move_spline.splineflags;

        if (move_spline.transportGuid)
        {
            //DEBUG_LOG("Setting transport opcode for %s", move_spline.transport->GetGuidStr().c_str());
            data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT);
            data << PackedGuid(move_spline.transportGuid);
            data << uint8(move_spline.transportSeat);
            data << uint8(0);
            data << (Vector3)move_spline.transportPos;
        }
        else
        {
            data << uint8(0);
            data << move_spline.spline.getPoint(move_spline.spline.first());
        }

        data << move_spline.GetId();

        switch(splineflags & MoveSplineFlag::Mask_Final_Facing)
        {
            default:
                data << uint8(MonsterMoveNormal);
                break;
            case MoveSplineFlag::Final_Target:
                data << uint8(MonsterMoveFacingTarget);
                data << move_spline.facing.target;
                break;
            case MoveSplineFlag::Final_Angle:
                data << uint8(MonsterMoveFacingAngle);
                data << NormalizeOrientation(move_spline.facing.angle);
                break;
            case MoveSplineFlag::Final_Point:
                data << uint8(MonsterMoveFacingSpot);
                data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
                break;
        }

        // add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
        splineflags.enter_cycle = move_spline.isCyclic();
        data << uint32(splineflags & ~MoveSplineFlag::Mask_No_Monster_Move);

        if (splineflags.animation)
        {
            data << splineflags.getAnimationId();
            data << move_spline.effect_start_time;
        }

        data << move_spline.Duration();

        if (splineflags.parabolic)
        {
            data << move_spline.vertical_acceleration;
            data << move_spline.effect_start_time;
        }
    }
Пример #8
0
void Channel::RequestList(std::string ch)
{
	if(!IsOnChannel(ch))
		logdebug("Requesting list of not joined channel '%s'",ch.c_str());
	WorldPacket wp;
	wp.SetOpcode(CMSG_CHANNEL_LIST);
	wp << ch;
	_worldSession->SendWorldPacket(wp);
}
Пример #9
0
void NetManager::cs_GetSchedule()
{
	WorldPacket packet;
	packet.clear();
	packet.SetOpcode(MSG_CS_GET_SCHEDULE);
	packet.AppendPacketString<uint8>(Player::getSingleton().getID());
	packet.SetLength(packet.size());
	sSocketMgr.SendPacket(LIFE_SOCKET_ID, &packet);
}
Пример #10
0
void LootRoll::Finalize()
{
    // this we will have to finalize with groups types.. for now
    // we'll just assume need before greed. person with highest roll
    // in need gets the item.

    uint32 highest = 0;
    int8 hightype = -1;
    Player *player = NULL;

    for(std::map<Player*, uint32>::iterator itr = NeedRolls.begin(); itr != NeedRolls.end(); ++itr)
    {
        if(itr->second > highest)
        {
            highest = itr->second;
            player = itr->first;
            hightype = NEED;
        }
    }

    if(highest == 0)
    {
        for(std::map<Player*, uint32>::iterator itr = GreedRolls.begin(); itr != GreedRolls.end(); ++itr)
        {
            if(itr->second > highest)
            {
                highest = itr->second;
                player = itr->first;
                hightype = GREED;
            }
        }
    }

    if(!player)
    {
        delete this;
        return;
    }

    WorldPacket data(34);
    data.SetOpcode(SMSG_LOOT_ROLL_WON);
    data << _guid << _slotid << _itemid << _itemunk1 << _itemunk2;
    data << player->GetGUID() << uint8(highest) << uint8(hightype);
    if(player->InGroup())
        player->GetGroup()->SendPacketToAll(&data);
    else
        player->GetSession()->SendPacket(&data);

    // Distribute the item.. yes i am lazy:D
    WorldPacket *tmp = new WorldPacket(1);
    tmp->SetOpcode(CMSG_AUTOSTORE_LOOT_ITEM);
    *tmp << uint8(_slotid);
    player->GetSession()->QueuePacket(tmp);

    delete this;
}
Пример #11
0
void WorldSession::SendEmote(uint32 id)
{
    if(!_logged)
        return;
    WorldPacket packet;
    int32 variation = 0; // randomized usually
    packet << id << (uint32)variation << GetMyChar()->GetTarget();
    packet.SetOpcode(CMSG_TEXT_EMOTE);
    SendWorldPacket(packet);
}
Пример #12
0
void WorldSession::SendPing(uint32 ping)
{
    if(!_logged)
        return;
    WorldPacket packet;
    packet << ping;
    packet << GetLagMS();
    packet.SetOpcode(CMSG_PING);
    SendWorldPacket(packet);
}
Пример #13
0
void WorldSession::SendQueryPlayerName(uint64 guid)
{
    if((!_logged) || guid==0)
        return;
    WorldPacket packet;
    packet << guid;
    packet.SetOpcode(CMSG_NAME_QUERY);
    SendWorldPacket(packet);
    // to prevent opcode spam, we need to make a list with already requested names
}
Пример #14
0
void NetManager::cs_DominoDownloadTilemap()
{
	WorldPacket packet;
	packet.clear();
	packet.SetOpcode(MSG_CS_DOMINO_DOWNLOAD_TILEMAP);
	packet.AppendPacketString<uint8>(Player::getSingleton().getID());
	packet << (int)1;
	packet.SetLength(packet.size());
	sSocketMgr.SendPacket(LIFE_SOCKET_ID, &packet);
}
Пример #15
0
void WorldSession::SendQueryItem(uint32 entry, uint64 guid) // is it a guid? not sure
{
    if(objmgr.ItemNonExistent(entry))
    {
        logdebug("Skipped query of item %u (was marked as nonexistent before)",entry);
        return;
    }
    logdebug("Sending Item query, id=%u",entry);
    WorldPacket packet;
    packet << entry << guid;
    packet.SetOpcode(CMSG_ITEM_QUERY_SINGLE);
    SendWorldPacket(packet);
}
Пример #16
0
void NetManager::cs_DominoUploadTilemap()
{
	TileMap& tilemap = DominoManager::getSingleton().getTileMap(0);
	WorldPacket packet;
	packet.clear();
	packet.SetOpcode(MSG_CS_DOMINO_UPLOAD_TILEMAP);
	packet.AppendPacketString<uint8>(Player::getSingleton().getID());
	packet << (int)1;
	packet << (int)tilemap.map.size();
	packet.writeVector(tilemap.map);
	packet.SetLength(packet.size());
	sSocketMgr.SendPacket(LIFE_SOCKET_ID, &packet);
}
Пример #17
0
void NetManager::cs_Login()
{
	// 定义协议包
	WorldPacket packet;
	packet.clear();
	// 设置协议头
	packet.SetOpcode(MSG_CS_LOGIN);
	// 加入字符串数据(uint8表示字符串长度所占字节,此处为1字节)
	packet.AppendPacketString<uint8>(Player::getSingleton().getID());
	// 设置协议长度
	packet.SetLength(packet.size());
	// 发送数据
	sSocketMgr.SendPacket(LIFE_SOCKET_ID, &packet);
}
Пример #18
0
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data)
{
    DEBUG_LOG("WORLD: Received CMSG_MOVE_SPLINE_DONE");

    MovementInfo movementInfo;                              // used only for proper packet read

    recv_data >> movementInfo;
    recv_data >> Unused<uint32>();                          // unk
    recv_data >> Unused<uint32>();                          // unk2

    // Forward packet to near players
    recv_data.SetOpcode(MSG_MOVE_STOP);
    recv_data.rpos(0);
    HandleMovementOpcodes(recv_data);
}
Пример #19
0
void Channel::Leave(std::string channel)
{
    for(std::vector<std::string>::iterator i = channels.begin(); i != channels.end(); i++)
	{
        if (*i == channel)
		{
		    // Send leave channel request
		    WorldPacket worldPacket;
		    worldPacket.SetOpcode(CMSG_LEAVE_CHANNEL);
			worldPacket << (uint32)0; // new since 2.0.x, maybe channel id
		    worldPacket << channel;
		    _worldSession->SendWorldPacket(worldPacket);
            return;
		}
	}
    log("Can't leave channel \"%s\": not joined",channel.c_str());
}
Пример #20
0
void WorldSession::HandleMinimapPingOpcode( WorldPacket & recv_data )
{
	if(!_player->IsInWorld()) return;
	CHECK_PACKET_SIZE(recv_data, 8);
	if(!_player->InGroup())
	return;
	Group * party= _player->GetGroup();
	if(!party)return;

	float x,y;
	recv_data >> x >>y;
	WorldPacket data;
	data.SetOpcode(MSG_MINIMAP_PING);
	data << _player->GetGUID();
	data << x << y;
	party->SendPacketToAllButOne(&data, _player);
}
Пример #21
0
void Channel::Join(std::string channel, std::string password)
{
	if (IsOnChannel(channel))
		return;

	// Send join channel request
	WorldPacket worldPacket;
	worldPacket.SetOpcode(CMSG_JOIN_CHANNEL);
    if(_worldSession->GetInstance()->GetConf()->client > CLIENT_CLASSIC_WOW)
    {
      worldPacket << (uint32)0; // new since 2.0.x, some channel ID? server answers us with that number later if channel joined
      worldPacket << (uint8)0;  // unk
      worldPacket << (uint8)0;  // unk, new since 2.2.x
    }
	worldPacket << channel << password;
	_worldSession->SendWorldPacket(worldPacket);
}
Пример #22
0
void CGroup::HandlerLevelUp(CRole *pCRole, WorldPacket &pkg)
{
	STC_CONF_GROUP_INFO *pUp = CConfGroupInfo::Find(GetwLevel() + 1);
	if (pUp == NULL)
	{
		pCRole->SendErrorMsg(ERRNO_MSG_ALREADY_FULL_LEVEL, CMD_SC_GROUP_LEVELUP_RESULT);
		return;
	}
	if (GetdwCredit() < GetdwNeedCredit())
	{
		pCRole->SendErrorMsg(ERRNO_MSG_CREDIT_NOT_ENOUGH, CMD_SC_GROUP_LEVELUP_RESULT);
		return;
	}
	SGroupMember *pSGroupMember = GetGroupMember(pCRole->GetdwAccountId());
	// admin verify
	if (!CConfGroupAdmin::GetVal(pSGroupMember->byPosion, E_GA_LEVELUP))
	{
		pCRole->SendErrorMsg(ERRNO_MSG_GROUP_NOT_AUTH, CMD_SC_GROUP_LEVELUP_RESULT);
		return;
	}
	
//	SetdwCredit(m_dwCredit - m_dwNeedCredit);	
	
	ChangeCredit(-m_dwNeedCredit);
	SetwLevel(m_wLevel + 1);

	if (Calculate())
	{
		pCRole->SendErrorMsg(ERRNO_MSG_CALCULATE, CMD_SC_GROUP_LEVELUP_RESULT);
		return;

	}
	// notify all group member
	WorldPacket info;
	PackProUpdate(info);
	SendDataToAllMember(&info);
	info.clear();

	info.SetOpcode(CMD_SC_GROUP_LEVELUP_RESULT);
	info << (uint16_t) 0;
	pCRole->SendPacket(&info);
	return;
}
 void CastGravityLapseFly()                              // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air...
 {
     std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
     for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i)
     {
         Unit* unit = Unit::GetUnit((*me), (*i)->getUnitGuid());
         if (unit && (unit->GetTypeId() == TYPEID_PLAYER))
         {
             // Also needs an exception in spell system.
             unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID());
             // Use packet hack
             WorldPacket data;
             data.SetOpcode(SMSG_MOVE_SET_CAN_FLY);
             data.append(unit->GetPackGUID());
             data << uint32(0);
             unit->SendMessageToSet(&data, true);
         }
     }
 }
        void RemoveGravityLapse()
        {
            std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin();
            for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i)
            {
                Unit* unit = Unit::GetUnit((*me), (*i)->getUnitGuid());
                if (unit && (unit->GetTypeId() == TYPEID_PLAYER))
                {
                    unit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
                    unit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);

                    WorldPacket data;
                    data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY);
                    data.append(unit->GetPackGUID());
                    data << uint32(0);
                    unit->SendMessageToSet(&data, true);
                }
            }
        }
Пример #25
0
void WorldSession::_HandleCompressedUpdateObjectOpcode(WorldPacket& recvPacket)
{
    uint32 realsize;
    recvPacket >> realsize;
    ZCompressor z;
    z.append(recvPacket.contents() + sizeof(uint32),recvPacket.size() - sizeof(uint32));
    z.Compressed(true);
    z.RealSize(realsize);
    z.Inflate();
    if(z.Compressed())
    {
        logerror("_HandleCompressedUpdateObjectOpcode(): Inflate() failed! size=%u realsize=%u",z.size(),realsize);
        return;
    }
    WorldPacket wp;
    wp.SetOpcode(recvPacket.GetOpcode());
    wp.append(z.contents(),z.size());

    _HandleUpdateObjectOpcode(wp);
}
Пример #26
0
void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets)
{
    // some spell cast packet including more data (for projectiles?)
    if (castFlags & 0x02)
    {
        // not sure about these two
        float elevation, speed;
        recvPacket >> elevation;
        recvPacket >> speed;

        targets.SetElevation(elevation);
        targets.SetSpeed(speed);

        uint8 hasMovementData;
        recvPacket >> hasMovementData;
        if (hasMovementData)
        {
            recvPacket.SetOpcode(recvPacket.read<uint32>());
            HandleMovementOpcodes(recvPacket);
        }
    }
Пример #27
0
void Group::RemovePlayer(Player* pPlayer)
{
	WorldPacket data;
	
	SubGroup *sg = GetSubGroup(pPlayer->GetSubGroup());
	ASSERT(sg); // something wrong here if that isn't right

	sg->RemovePlayer(pPlayer);
	pPlayer->SetGroup(NULL);
	if(pPlayer->GetSession() != NULL)
	{
		SendNullUpdate(pPlayer);

		//pPlayer->RemoveAllAreaAuras();

		data.SetOpcode(SMSG_GROUP_DESTROYED);
		pPlayer->GetSession()->SendPacket(&data);

		data.Initialize(SMSG_PARTY_COMMAND_RESULT);
		data << uint32(2) << uint8(0) << uint32(0);  // you leave the group
		pPlayer->GetSession()->SendPacket(&data);
	}

	if(m_MemberCount < 2)
	{
		Disband();
		return;
	}

	Player *newPlayer = FindFirstPlayer();

	if(m_Looter == pPlayer)
		m_Looter = newPlayer;

	if(m_Leader == pPlayer)
		SetLeader(newPlayer);
	else
		Update();
}
Пример #28
0
void WorldSession::SendChatMessage(uint32 type, uint32 lang, std::string msg, std::string to)
{
    if((!_logged) || msg.empty())
        return;
	WorldPacket packet;
	packet << type << lang;
	switch(type){
		case CHAT_MSG_WHISPER:
            if(to.empty())
                return;
			packet << to << msg;
			break;
		case CHAT_MSG_CHANNEL:
            if(to.empty() /*|| !_channels->IsOnChannel(to)*/)
                return;
			packet << to << msg;
			break;
        default:
            packet << msg;
	}
    packet.SetOpcode(CMSG_MESSAGECHAT);
	SendWorldPacket(packet);
}
Пример #29
0
void WServer::HandleSwitchServer(WorldPacket & pck)
{
	uint32 sessionid, guid, mapid, instanceid;
	LocationVector location;
	float o;

	pck >> sessionid >> guid >> mapid >> instanceid >> location >> o;
	Session* s=sClientMgr.GetSession(sessionid);

	if (s == NULL)
		return;

	//so, switch our server, f**k the old one
	s->SetNextServer();

	WorldPacket data;
	data.SetOpcode(ISMSG_PLAYER_LOGIN);
	data << guid << mapid << instanceid;
	data << s->GetAccountId() << s->GetAccountFlags() << s->GetSessionId();
	data << s->GetAccountPermissions() << s->GetAccountName() << s->GetClientBuild();


	s->GetServer()->SendPacket(&data);
}
Пример #30
0
void WorldSocket::OnRead()
{
    TcpSocket::OnRead();
    if(!ibuf.GetLength())
    {
        this->CloseAndDelete();
        return;
    }
    while(ibuf.GetLength() > 0) // when all packets from the current ibuf are transformed into WorldPackets the remaining len will be zero
    {

        if(_gothdr) // already got header, this packet has to be the data part
        {
            ASSERT(_remaining > 0); // case pktsize==0 is handled below
            if(ibuf.GetLength() < _remaining)
            {
                DEBUG(logdebug("Delaying WorldPacket generation, bufsize is %u but should be >= %u",ibuf.GetLength(),_remaining));
                break;
            }
            _gothdr=false;
            WorldPacket *wp = new WorldPacket(_remaining);
            wp->resize(_remaining);
            ibuf.Read((char*)wp->contents(),_remaining);
            wp->SetOpcode(_opcode);
            GetSession()->AddToPktQueue(wp);
        }
        else // no pending header stored, so this packet must be a header
        {
            if(ibuf.GetLength() < sizeof(ServerPktHeader))
            {
                DEBUG(logdebug("Delaying header reading, bufsize is %u but should be >= %u",ibuf.GetLength(),sizeof(ServerPktHeader)));
                break;
            }

            if(GetSession()->GetInstance()->GetConf()->client > CLIENT_TBC)//Funny, old sources have this in TBC already...
            {
              // read first byte and check if size is 3 or 2 bytes
              uint8 firstSizeByte;
              ibuf.Read((char*)&firstSizeByte, 1);
              (_crypt.*pDecryptRecv)(&firstSizeByte, 1);
              if (firstSizeByte & 0x80) // got large packet
              {
                  ServerPktHeaderBig hdr;
                  ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // read *big* header, except first byte
                  (_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // decrypt 2 of 3 bytes (first one already decrypted above) of size, and cmd
                  hdr.size[0] = firstSizeByte; // assign missing first byte

                  uint32 realsize = ((hdr.size[0]&0x7F) << 16) | (hdr.size[1] << 8) | hdr.size[2];
                  _remaining = realsize - 2;
                  _opcode = hdr.cmd;
              }
              else // "normal" packet
              {
                  ServerPktHeader hdr;
                  ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // read header, except first byte
                  (_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // decrypt all except first
                  hdr.size |= firstSizeByte; // add already decrypted first byte

                  _remaining = ntohs(hdr.size) - 2;
                  _opcode = hdr.cmd;
              }
            }
            else
            {
              ServerPktHeader hdr;
              ibuf.Read(((char*)&hdr), sizeof(ServerPktHeader)); // read header
              (_crypt.*pDecryptRecv)(((uint8*)&hdr), sizeof(ServerPktHeader)); // decrypt all

              _remaining = ntohs(hdr.size) - 2;
              _opcode = hdr.cmd;

            }

            if(_opcode > MAX_OPCODE_ID)
            {
                logcritical("CRYPT ERROR: opcode=%u, remain=%u",_opcode,_remaining); // this should never be the case!
                GetSession()->GetInstance()->SetError(); // no way to recover the crypt, must exit
                // if the crypt gets messy its hardly possible to recover it, especially if we dont know
                // the length of the following data part
                // TODO: invent some way how to recover the crypt (reconnect?)
                return;
            }
            // the header is fine, now check if there are more data
            if(_remaining == 0) // this is a packet with no data (like CMSG_NULL_ACTION)
            {
                WorldPacket *wp = new WorldPacket;
                wp->SetOpcode(_opcode);
                GetSession()->AddToPktQueue(wp);
            }
            else // there is a data part to fetch
            {
                _gothdr=true; // only got the header, next packet will contain the data
            }
        }
    }
}