/// Only _static_ data is sent in this packet !!! void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData) { uint32 entry; recvData >> entry; uint64 guid; recvData >> guid; const GameObjectTemplate* info = sObjectMgr->GetGameObjectTemplate(entry); if (info) { std::string Name; std::string IconName; std::string CastBarCaption; Name = info->name; IconName = info->IconName; CastBarCaption = info->castBarCaption; int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { if (GameObjectLocale const* gl = sObjectMgr->GetGameObjectLocale(entry)) { ObjectMgr::GetLocaleString(gl->Name, loc_idx, Name); ObjectMgr::GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption); } } sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); data << uint32(entry); data << uint32(info->type); data << uint32(info->displayId); data << Name; data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") data << info->unk1; // 2.0.3, string data.append(info->raw.data, MAX_GAMEOBJECT_DATA); data << float(info->size); // go size for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i) data << uint32(info->questItems[i]); // itemId[6], quest drop SendPacket(&data); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); } else { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", GUID_LOPART(guid), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 4); data << uint32(entry | 0x80000000); SendPacket(&data); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); } }
bool AddonMgr::AppendPublicKey(WorldPacket & data, std::string & AddonName, uint32 CRC) { if(CRC == 0x4C1C776D) { // Open public key file with that addon AddonDataItr itr = mAddonData.find(AddonName); if(itr != mAddonData.end()) data.append(itr->second); else { // open the file char path[500]; snprintf(path, 500, "addons\\%s.pub", AddonName.c_str()); FILE* f = fopen(path, "rb"); if(f != 0) { // read the file into a bytebuffer ByteBuffer buf; fseek(f, 0, SEEK_END); uint32 length = 264/*ftell(f)*/; fseek(f, 0, SEEK_SET); buf.resize(length); fread((void*)buf.contents(), length, 1, f); fclose(f); mAddonData[AddonName] = buf; data.append(buf); } else { ByteBuffer buf; buf.append(PublicKey, 264); mAddonData[AddonName] = buf; data.append(buf); } } return true; } return false; }
void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text) { int len = text ? strlen(text) : 0; WorldPacket data; data.Initialize( SMSG_GMTICKET_GETTICKET, (4+len+4) ); data << uint32(6); if(len > 0) data.append((uint8 *)text,len+1); else data << uint32(0); SendPacket( &data ); }
/// Only _static_ data is sent in this packet !!! void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData) { uint32 entry; recvData >> entry; ObjectGuid guid; recvData >> guid; const GameObjectTemplate* info = sObjectMgr->GetGameObjectTemplate(entry); if (info) { std::string Name; std::string IconName; std::string CastBarCaption; Name = info->name; IconName = info->IconName; CastBarCaption = info->castBarCaption; LocaleConstant localeConstant = GetSessionDbLocaleIndex(); if (localeConstant >= LOCALE_enUS) if (GameObjectLocale const* gameObjectLocale = sObjectMgr->GetGameObjectLocale(entry)) { ObjectMgr::GetLocaleString(gameObjectLocale->Name, localeConstant, Name); ObjectMgr::GetLocaleString(gameObjectLocale->CastBarCaption, localeConstant, CastBarCaption); } TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); data << uint32(entry); data << uint32(info->type); data << uint32(info->displayId); data << Name; data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") data << info->unk1; // 2.0.3, string data.append(info->raw.data, MAX_GAMEOBJECT_DATA); data << float(info->size); // go size data << int32(info->unkInt32); // 4.x, unknown SendPacket(&data); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); } else { TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (%s, ENTRY: %u)", guid.ToString().c_str(), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 4); data << uint32(entry | 0x80000000); SendPacket(&data); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); } }
void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) { uint64 clientcount = 0; int datalen = 8; int countcheck = 0; WorldPacket data; Log::getSingleton( ).outDebug( "WORLD: Recvd CMSG_WHO Message" ); #ifndef ENABLE_GRID_SYSTEM ObjectMgr::PlayerMap::const_iterator itr; for (itr = objmgr.Begin<Player>(); itr != objmgr.End<Player>(); itr++) #else ObjectAccessor::PlayerMapType &m(ObjectAccessor::Instance().GetPlayers()); for(ObjectAccessor::PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr) #endif { if ( itr->second->GetName() ) { clientcount++; datalen = datalen + strlen(itr->second->GetName()) + 1 + 21; } } data.Initialize( SMSG_WHO ); data << uint64( clientcount ); #ifndef ENABLE_GRID_SYSTEM for (itr = objmgr.Begin<Player>(); itr != objmgr.End<Player>(); itr++) #else for(ObjectAccessor::PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr) #endif { if ( itr->second->GetName() && (countcheck < clientcount)) { countcheck++; data.append(itr->second->GetName() , strlen(itr->second->GetName()) + 1); data << uint8( 0x00 ); data << uint32( itr->second->getLevel() ); data << uint32( itr->second->getClass() ); data << uint32( itr->second->getRace() ); data << uint32( itr->second->GetZoneId() ); data << uint32( 0x00000000 ); // this is the guild id...once we have guilds working it'll go here. } } WPAssert(data.size() == datalen); SendPacket(&data); }
void WorldSession::HandlePetitionShowListOpcode( WorldPacket & recv_data ) { WorldPacket data; uint64 guid; unsigned char tdata[21] = { 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x16, 0x00, 0x00, 0xef, 0x23, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }; recv_data >> guid; data.Initialize( SMSG_PETITION_SHOWLIST ); data << guid; data.append( tdata, sizeof(tdata) ); SendPacket( &data ); }
void operator()(WorldPacket& data, int32 loc_idx) { char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL; uint32 namlen = (nam ? strlen(nam) : 0) + 1; data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); data << i_player.GetGUID(); data << (uint32)i_text_emote; data << i_emote_num; data << (uint32)namlen; if( namlen > 1 ) data.append(nam, namlen); else data << (uint8)0x00; }
void operator()(WorldPacket& data, int32 loc_idx) { char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL; uint32 namlen = (nam ? strlen(nam) : 0) + 1; data.Initialize(SMSG_TEXT_EMOTE, (20 + namlen)); data << ObjectGuid(i_player.GetObjectGuid()); data << uint32(i_text_emote); data << uint32(i_emote_num); data << uint32(namlen); if (namlen > 1) data.append(nam, namlen); else data << uint8(0x00); }
/// Only _static_ data send in this packet !!! void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) { uint32 entryID; recv_data >> entryID; recv_data.read_skip<uint64>(); // guid const GameObjectInfo *info = ObjectMgr::GetGameObjectInfo(entryID); if(info) { std::string Name = info->name; int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { GameObjectLocale const *gl = sObjectMgr.GetGameObjectLocale(entryID); if (gl) { if (gl->Name.size() > size_t(loc_idx) && !gl->Name[loc_idx].empty()) Name = gl->Name[loc_idx]; } } sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 150 ); data << uint32(entryID); data << uint32(info->type); data << uint32(info->displayId); data << Name; data << uint16(0) << uint8(0) << uint8(0); // name2, name3, name4 data.append(info->raw.data, 24); //data << float(info->size); // go size , to check SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" ); } else { uint64 guid; recv_data >> guid; sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", GUID_LOPART(guid), entryID ); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 ); data << uint32(entryID | 0x80000000); SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" ); } }
bool UpdateData::buildPacket(WorldPacket& packet, bool hasTransport) { ByteBuffer buf(m_data.size() + 10 + m_guidList.size() * 8); buf << (u_int)(!m_guidList.empty() ? m_blockCount + 1 : m_blockCount); buf << (u_char)(hasTransport ? 1 : 0); if (!m_guidList.empty()) { buf << (u_char)UPDATETYPE_OUT_OF_RANGE_OBJECTS; buf << (u_int)m_guidList.size(); for (IDList::const_iterator itr = m_guidList.begin(); itr != m_guidList.end(); ++itr) { buf << (u_char)0xFF; buf << (u_int64)*itr; } } buf.append(m_data); packet.clear(); // 大小超过50字节的数据包要压缩 if (m_data.size() > 50) { u_int destSize = (u_int)buf.size() + buf.size() / 10 + 16; packet.resize(destSize); packet.put(0, (u_int)buf.size()); compress(const_cast<u_char*>(packet.contents()) + sizeof(u_int), &destSize, (void*)buf.contents(), (u_int)buf.size()); if (destSize == 0) return false; packet.resize(destSize + sizeof(u_int)); packet.setOpcode(SMSG_COMPRESSED_UPDATE_OBJECT); } else { packet.append(buf); packet.setOpcode(SMSG_UPDATE_OBJECT); } return true; }
void BlackMarketMgr::BuildBlackMarketAuctionsPacket(WorldPacket& data, uint32 guidLow) { uint32 count = 0; data << uint32(time(NULL)); for (auto const &kvPair : m_bmAuctionsMap) if (kvPair.second->IsActive()) ++count; data.WriteBits(count, 18); ByteBuffer datas; for (auto const &kvPair : m_bmAuctionsMap) { auto const auction = kvPair.second; if (!auction->IsActive()) continue; // Is owner data.WriteBit(guidLow == auction->bidder); uint64 currentBid = auction->bidder ? auction->bid : 0; uint64 nextBidPrice = auction->bidder ? auction->bid + GetAuctionOutBid(auction->bid) : auction->bid; uint64 upPrice = auction->bidder ? nextBidPrice - currentBid : 1; datas << uint32(auction->bmTemplate->itemEntry); datas << uint32(auction->bmTemplate->seller); datas << uint32(auction->id); datas << uint32(auction->bidderCount); datas << uint32(auction->TimeLeft()); datas << uint64(currentBid); datas << uint32(auction->bmTemplate->itemCount); datas << uint32(0); // Unk datas << uint64(nextBidPrice); datas << uint64(upPrice); } data.FlushBits(); if (datas.size()) data.append(datas); TC_LOG_DEBUG("network", ">> Sent %u BlackMarket Auctions", count); }
void WorldSession::HandleGMTicketGetTicketOpcode( WorldPacket & recv_data ) { WorldPacket data; uint64 guid; std::stringstream query,query1; Field *fields; guid = GetPlayer()->GetGUID(); query << "SELECT COUNT(*) FROM `gmtickets` where guid='" << guid << "'"; QueryResult *result = sDatabase.Query( query.str().c_str() ); if (result) { int cnt; fields = result->Fetch(); cnt = fields[0].GetUInt32(); if ( cnt > 0 ) { data.Initialize( SMSG_GMTICKET_GETTICKET ); query1 << "SELECT * FROM `gmtickets` where guid='" << guid << "'"; QueryResult *result = sDatabase.Query( query1.str().c_str() ); fields = result->Fetch(); printf( "query=%s\n", query1.str().c_str() ); char tickettext[255]; strcpy( tickettext,fields[2].GetString() ); data << uint32(6); // means we have open tickets data.append((uint8 *)tickettext,strlen(tickettext)+1); data << uint8(0); // ?? data << uint8(3); // ?? SendPacket( &data ); } else { data << uint32(1); // all !6 means we have no open tickets data << uint32(0); data << uint8(0); data << uint8(0); SendPacket( &data ); } } delete result; }
void BlackMarketMgr::BuildBlackMarketAuctionsPacket(WorldPacket& data, uint32 guidLow) { uint32 count = 0; ByteBuffer datas; data << uint32(time(NULL)); for (BMAuctionEntryMap::const_iterator itr = GetAuctionsBegin(); itr != GetAuctionsEnd(); ++itr) if (itr->second->IsActive()) ++count; data.WriteBits(count, 18); for (BMAuctionEntryMap::const_iterator itr = GetAuctionsBegin(); itr != GetAuctionsEnd(); ++itr) { BMAuctionEntry* auction = itr->second; if (!auction->IsActive()) continue; data.WriteBit(guidLow == auction->bidder); // Is owner uint64 currentBid = auction->bidder ? auction->bid : 0; uint64 nextBidPrice = auction->bidder ? auction->bid + GetAuctionOutBid(auction->bid) : auction->bid; uint64 upPrice = auction->bidder ? nextBidPrice - currentBid : 1; datas << uint32(auction->bm_template->itemEntry); datas << uint64(nextBidPrice); datas << uint64(currentBid); datas << uint32(0); // Unk datas << uint32(auction->id); datas << uint32(auction->bm_template->seller); datas << uint64(upPrice); datas << uint32(auction->TimeLeft()); datas << uint32(auction->bidderCount); datas << uint32(auction->bm_template->itemCount); } data.FlushBits(); if (datas.size()) data.append(datas); sLog->outInfo(LOG_FILTER_NETWORKIO, ">> Sent %u BlackMarket Auctions", count); }
/// Only _static_ data send in this packet !!! void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) { uint32 entryID; recv_data >> entryID; ObjectGuid guid; recv_data >> guid; const GameObjectInfo *info = ObjectMgr::GetGameObjectInfo(entryID); if(info) { std::string Name = info->name; int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { GameObjectLocale const *gl = sObjectMgr.GetGameObjectLocale(entryID); if (gl) { if (gl->Name.size() > size_t(loc_idx) && !gl->Name[loc_idx].empty()) Name = gl->Name[loc_idx]; } } DETAIL_LOG("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 150 ); data << uint32(entryID); data << uint32(info->type); data << uint32(info->displayId); data << Name; data << uint16(0) << uint8(0) << uint8(0); // name2, name3, name4 data.append(info->raw.data, 24); //data << float(info->size); // go size , to check SendPacket( &data ); DEBUG_LOG( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" ); } else { DEBUG_LOG("WORLD: CMSG_GAMEOBJECT_QUERY - Guid: %s Entry: %u Missing gameobject info!", guid.GetString().c_str(), entryID); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 ); data << uint32(entryID | 0x80000000); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" ); } }
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); } } }
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 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); }
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); if(len) pck->append((const uint8*)data, len); _queue.Push(pck); queueLock.Release(); } }
void AddonMgr::SendAddonInfoPacket(WorldPacket* source, uint32 pos, WorldSession* m_session) { WorldPacket returnpacket; returnpacket.Initialize(SMSG_ADDON_INFO); source->ResetRead(); source->read_skip(52); uint32 addonSize; *source >> addonSize; uint32 realsize; uLongf rsize; //*source >> realsize; //rsize = realsize; rsize = addonSize; size_t position = source->rpos(); ByteBuffer unpacked; unpacked.resize(rsize); int32 result; result = uncompress((uint8*)unpacked.contents(), &rsize, (uint8*)(*source).contents() + position, (uLong)((*source).size() - position)); if (result != Z_OK) { sLog.outError("Decompression of addon section of CMSG_AUTH_SESSION failed."); return; } sLog.outDetail("Decompression of addon section of CMSG_AUTH_SESSION succeeded."); uint32 addoncount; unpacked >> addoncount; if (addoncount > 100) return; //have a hunch they are f*****g with us uint8 Enable; // based on the parsed files from retool uint32 crc; uint32 unknown; bool have_new_addons = false; std::string name; for (uint32 i = 0; i< addoncount; ++i) { unpacked >> name; unpacked >> Enable; unpacked >> crc; unpacked >> unknown; // Hacky fix, Yea I know its a hacky fix I will make a proper handler one's I got the crc crap if (crc != 0x4C1C776D) // CRC of public key version 2.0.1 { returnpacket.append(PublicKey, 264); // part of the hacky fix have_new_addons = true; } else returnpacket << uint8(0x02) << uint8(0x01) << uint8(0x00) << uint32(0) << uint8(0); if (unpacked.rpos() >= unpacked.wpos()) break; } if (have_new_addons == false) { returnpacket << uint32(0); //this is a counter ! } m_session->SendPacket(&returnpacket); }
bool ChatHandler::HandleModifyMountCommand(const char* args) { WorldPacket data; if(!*args) return false; uint16 mId = 1147; float speed = (float)15; uint32 num = 0; num = atoi((char*)args); switch(num) { case 1: mId=14340; break; case 2: mId=4806; break; case 3: mId=6471; break; case 4: mId=12345; break; case 5: mId=6472; break; case 6: mId=6473; break; case 7: mId=10670; break; case 8: mId=10719; break; case 9: mId=10671; break; case 10: mId=10672; break; case 11: mId=10720; break; case 12: mId=14349; break; case 13: mId=11641; break; case 14: mId=12244; break; case 15: mId=12242; break; case 16: mId=14578; break; case 17: mId=14579; break; case 18: mId=14349; break; case 19: mId=12245; break; case 20: mId=14335; break; case 21: mId=207; break; case 22: mId=2328; break; case 23: mId=2327; break; case 24: mId=2326; break; case 25: mId=14573; break; case 26: mId=14574; break; case 27: mId=14575; break; case 28: mId=604; break; case 29: mId=1166; break; case 30: mId=2402; break; case 31: mId=2410; break; case 32: mId=2409; break; case 33: mId=2408; break; case 34: mId=2405; break; case 35: mId=14337; break; case 36: mId=6569; break; case 37: mId=10661; break; case 38: mId=10666; break; case 39: mId=9473; break; case 40: mId=9476; break; case 41: mId=9474; break; case 42: mId=14374; break; case 43: mId=14376; break; case 44: mId=14377; break; case 45: mId=2404; break; case 46: mId=2784; break; case 47: mId=2787; break; case 48: mId=2785; break; case 49: mId=2736; break; case 50: mId=2786; break; case 51: mId=14347; break; case 52: mId=14346; break; case 53: mId=14576; break; case 54: mId=9695; break; case 55: mId=9991; break; case 56: mId=6448; break; case 57: mId=6444; break; case 58: mId=6080; break; case 59: mId=6447; break; case 60: mId=4805; break; case 61: mId=9714; break; case 62: mId=6448; break; case 63: mId=6442; break; case 64: mId=14632; break; case 65: mId=14332; break; case 66: mId=14331; break; case 67: mId=8469; break; case 68: mId=2830; break; case 69: mId=2346; break; default: SendSysMessage(LANG_NO_MOUNT); return true; } Player *chr = getSelectedPlayer(); if (chr == NULL) { SendSysMessage(LANG_NO_CHAR_SELECTED); return true; } PSendSysMessage(LANG_YOU_GIVE_MOUNT, chr->GetName()); char buf[256]; sprintf((char*)buf,LANG_MOUNT_GIVED, m_session->GetPlayer()->GetName()); FillSystemMessageData(&data, m_session, buf); chr->GetSession()->SendPacket(&data); chr->SetUInt32Value( UNIT_FIELD_FLAGS , 0x001000 ); chr->Mount(mId); data.Initialize( SMSG_FORCE_RUN_SPEED_CHANGE, (8+4+4) ); data.append(chr->GetPackGUID()); data << (uint32)0; data << float(speed); chr->SendMessageToSet( &data, true ); data.Initialize( SMSG_FORCE_SWIM_SPEED_CHANGE, (8+4+4) ); data.append(chr->GetPackGUID()); data << (uint32)0; data << float(speed); chr->SendMessageToSet( &data, true ); return true; }
/// Update the WorldSession (triggered by World update) bool WorldSession::Update(uint32 diff, PacketFilter& updater) { if (updater.ProcessLogout()) { UpdateTimeOutTime(diff); if (IsConnectionIdle()) m_Socket->CloseSocket(); } HandleTeleportTimeout(updater.ProcessLogout()); uint32 _startMSTime = getMSTime(); WorldPacket* packet = NULL; WorldPacket* movementPacket = NULL; bool deletePacket = true; WorldPacket* firstDelayedPacket = NULL; uint32 processedPackets = 0; while (m_Socket && !m_Socket->IsClosed() && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { if (packet->GetOpcode() < NUM_MSG_TYPES) { OpcodeHandler &opHandle = opcodeTable[packet->GetOpcode()]; try { switch (opHandle.status) { case STATUS_LOGGEDIN: if (!_player) { // pussywizard: such packets were sent to do something for a character that has already logged out, skip them } else if (!_player->IsInWorld()) { // pussywizard: such packets may do something important and the player is just being teleported, move to the end of the queue // pussywizard: previously such were skipped, so leave it as it is xD proper code below if we wish to change that // pussywizard: requeue only important packets not related to maps (PROCESS_THREADUNSAFE) /*if (opHandle.packetProcessing == PROCESS_THREADUNSAFE) { if (!firstDelayedPacket) firstDelayedPacket = packet; deletePacket = false; QueuePacket(packet); }*/ } else { if (opHandle.isGrouppedMovementOpcode) { if (movementPacket) delete movementPacket; movementPacket = new WorldPacket(packet->GetOpcode(), 0); movementPacket->append(*((ByteBuffer*)packet)); } else { if (movementPacket) { HandleMovementOpcodes(*movementPacket); delete movementPacket; movementPacket = NULL; } sScriptMgr->OnPacketReceive(this, *packet); #ifdef ELUNA if (!sEluna->OnPacketReceive(this, *packet)) break; #endif (this->*opHandle.handler)(*packet); } } break; case STATUS_TRANSFER: if (_player && !_player->IsInWorld()) { if (movementPacket) { delete movementPacket; movementPacket = NULL; } sScriptMgr->OnPacketReceive(this, *packet); #ifdef ELUNA if (!sEluna->OnPacketReceive(this, *packet)) break; #endif (this->*opHandle.handler)(*packet); } break; case STATUS_AUTHED: if (m_inQueue) // prevent cheating break; sScriptMgr->OnPacketReceive(this, *packet); #ifdef ELUNA if (!sEluna->OnPacketReceive(this, *packet)) break; #endif (this->*opHandle.handler)(*packet); break; case STATUS_NEVER: break; case STATUS_UNHANDLED: break; } } catch(ByteBufferException &) { sLog->outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); if (sLog->IsOutDebug()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Dumping error causing packet:"); packet->hexlike(); } } } if (deletePacket) delete packet; else deletePacket = true; if (++processedPackets >= 150) // limit (by count) packets processed in one update, prevent DDoS break; if (getMSTimeDiff(_startMSTime, getMSTime()) >= 3) // limit (by time) packets processed in one update, prevent DDoS break; } if (movementPacket) { if (_player && _player->IsInWorld()) HandleMovementOpcodes(*movementPacket); delete movementPacket; } if (m_Socket && !m_Socket->IsClosed()) ProcessQueryCallbacks(); if (updater.ProcessLogout()) { time_t currTime = time(NULL); if (ShouldLogOut(currTime) && !m_playerLoading) LogoutPlayer(true); if (m_Socket && !m_Socket->IsClosed() && _warden) _warden->Update(); if (m_Socket && m_Socket->IsClosed()) { m_Socket->RemoveReference(); m_Socket = NULL; } if (!m_Socket) return false; } return true; }
void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) { WorldPacket data; uint32 text_emote, unk; uint64 guid; recv_data >> text_emote; recv_data >> unk; recv_data >> guid; const char *nam = 0; uint32 namlen = 1; #ifndef ENABLE_GRID_SYSTEM Creature *pCreature = objmgr.GetObject<Creature>( guid ); if(pCreature) { nam = pCreature->GetName(); namlen = strlen( nam ) + 1; } else { Player *pChar = objmgr.GetObject<Player>( guid ); if(pChar) { nam = pChar->GetName(); namlen = strlen(nam) + 1; } } #else // gets the name of either a unit or a player.. same thing Unit* unit = ObjectAccessor::Instance().GetUnit(*_player, guid); Creature *pCreature = dynamic_cast<Creature *>(unit); if( pCreature != NULL ) { nam = pCreature->GetName(); namlen = strlen(nam) + 1; } { Player *pChar = dynamic_cast<Player *>(unit); if( pChar != NULL ) { nam = pChar->GetName(); namlen = strlen(nam) + 1; } } #endif emoteentry *em = sEmoteStore.LookupEntry(text_emote); if (em) // server crashes with some emotes, that arent in dbc { uint32 emote_anim = em->textid; data.Initialize(SMSG_EMOTE); data << (uint32)emote_anim; data << GetPlayer()->GetGUID(); WPAssert(data.size() == 12); sWorld.SendGlobalMessage(&data); data.Initialize(SMSG_TEXT_EMOTE); data << GetPlayer()->GetGUID(); data << (uint32)text_emote; data << (uint32)0xFF; // dunno whats that- send by server when using emote w/o target data << (uint32)namlen; if( namlen > 1 ) { data.append(nam, namlen); } else { data << (uint8)0x00; } WPAssert(data.size() == 20 + namlen); SendPacket( &data ); sWorld.SendGlobalMessage(&data, this); } }
void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,4+4+8); uint32 text_emote, emoteNum; uint64 guid; recv_data >> text_emote; recv_data >> emoteNum; recv_data >> guid; const char *nam = 0; uint32 namlen = 1; Unit* unit = ObjectAccessor::Instance().GetUnit(*_player, guid); Creature *pCreature = dynamic_cast<Creature *>(unit); if( pCreature != NULL ) { nam = pCreature->GetCreatureInfo()->Name; namlen = (nam ? strlen(nam) : 0) + 1; } { Player *pChar = dynamic_cast<Player *>(unit); if( pChar != NULL ) { nam = pChar->GetName(); namlen = (nam ? strlen(nam) : 0) + 1; } } EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); if (em) { uint32 emote_anim = em->textid; WorldPacket data; switch(emote_anim) { case EMOTE_STATE_SLEEP: case EMOTE_STATE_SIT: case EMOTE_STATE_KNEEL: break; default: data.Initialize(SMSG_EMOTE, 12); data << (uint32)emote_anim; data << GetPlayer()->GetGUID(); WPAssert(data.size() == 12); GetPlayer()->SendMessageToSet( &data, true ); break; } data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); data << GetPlayer()->GetGUID(); data << (uint32)text_emote; data << emoteNum; data << (uint32)namlen; if( namlen > 1 ) { data.append(nam, namlen); } else { data << (uint8)0x00; } GetPlayer()->SendMessageToSet( &data, true ); //Send scripted event call if (pCreature && Script) Script->ReceiveEmote(GetPlayer(),pCreature,emote_anim); } }
/// Only _static_ data send in this packet !!! void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,4+8); uint32 entryID; recv_data >> entryID; const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID); if(info) { std::string Name; std::string IconName; std::string CastBarCaption; Name = info->name; IconName = info->IconName; CastBarCaption = info->castBarCaption; int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { GameObjectLocale const *gl = objmgr.GetGameObjectLocale(entryID); if (gl) { if (gl->Name.size() > size_t(loc_idx) && !gl->Name[loc_idx].empty()) Name = gl->Name[loc_idx]; if (gl->CastBarCaption.size() > size_t(loc_idx) && !gl->CastBarCaption[loc_idx].empty()) CastBarCaption = gl->CastBarCaption[loc_idx]; } } sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 150 ); data << uint32(entryID); data << uint32(info->type); data << uint32(info->displayId); data << Name; data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") data << info->unk1; // 2.0.3, string data.append(info->raw.data, 24); data << float(info->size); // go size for(uint32 i = 0; i < 4; ++i) data << uint32(info->questItems[i]); // itemId[4], quest drop SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" ); } else { uint64 guid; recv_data >> guid; sLog.outDebug( "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", GUID_LOPART(guid), entryID ); WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 ); data << uint32(entryID | 0x80000000); SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE" ); } }
void WorldSession::HandleGameObjectStatsOpcode(WorldPacket & recv_data) { uint64 guid; uint32 entryID; recv_data >> entryID; recv_data >> guid; if (Chest == true) { entryID = Chestentry; guid = Chestguid; --guid; Chest = false; } const GameObjectTemplate *info = sObjectMgr->GetGameObjectTemplate(entryID); if (info) { std::string Name; std::string IconName; std::string CastBarCaption; Name = info->name; IconName = info->IconName; CastBarCaption = info->castBarCaption; int loc_idx = GetSessionDbLocaleIndex(); if (loc_idx >= 0) { if (GameObjectLocale const *gl = sObjectMgr->GetGameObjectLocale(entryID)) { sObjectMgr->GetLocaleString(gl->Name, loc_idx, Name); sObjectMgr->GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption); } } sLog->outDetail("WORLD: CMSG_GAME_OBJECT_STATS '%s' - Entry: %u. ", info->name.c_str(), entryID); WorldPacket data (SMSG_GAME_OBJECT_STATS, 200); data << uint32(entryID); data << uint32(info->type); data << uint32(info->displayId); data << Name; data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") data << info->unk1; // 2.0.3, string data.append(info->raw.data, MAX_GAMEOBJECT_DATA); data << float(info->size); // go size for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i) data << uint32(info->questItems[i]); // itemId[6], quest drop data << uint32(info->unk2); // Found in 4.2.0, data from gameobjectcache.wdb SendPacket(&data); sLog->outDebug("WORLD: Sent SMSG_GAME_OBJECT_STATS"); } else { sLog->outDebug("WORLD: CMSG_GAME_OBJECT_STATS - Missing gameobject stats for (GUID: %u, ENTRY: %u)", GUID_LOPART(guid), entryID); WorldPacket data (SMSG_GAME_OBJECT_STATS, 4); data << uint32(entryID | 0x80000000); SendPacket(&data); sLog->outDebug("WORLD: Sent SMSG_GAME_OBJECT_STATS"); } }
void AddonMgr::SendAddonInfoPacket(WorldPacket *source, uint32 pos, WorldSession *m_session) { WorldPacket returnpacket; returnpacket.Initialize(SMSG_ADDON_INFO); // SMSG_ADDON_INFO uint32 realsize; uLongf rsize; try { *source >> realsize; } catch (ByteBuffer::error &) { DEBUG_LOG("AddonMgr","Warning, Incomplete auth session sent."); return; } rsize = realsize; size_t position = source->rpos(); ByteBuffer unpacked; unpacked.resize(realsize); if((source->size() - position) < 4 || realsize == 0) { // we shouldnt get here.. but just in case this will stop any crash here. DEBUG_LOG("AddonMgr","Warning, Incomplete auth session sent."); return; } int32 result; result = uncompress((uint8*)unpacked.contents(), &rsize, (uint8*)(*source).contents() + position, (uLong)((*source).size() - position)); if(result != Z_OK) { DEBUG_LOG("AddonMgr","Decompression of addon section of CMSG_AUTH_SESSION failed."); return; } DEBUG_LOG("AddonMgr","Decompression of addon section of CMSG_AUTH_SESSION succeeded."); uint32 addons; // Added in 3.0.8 uint8 Enable; // based on the parsed files from retool uint32 crc; uint32 unknown; unpacked >> addons; size_t p = unpacked.rpos(); if( p + (addons*10) > unpacked.size() - p - 4) { // stupid f****r, trying to make us waste CPU cycles m_session->Disconnect(); return; } std::string name; for (uint32 i = 0; i < addons; ++i) { unpacked >> name; unpacked >> Enable; unpacked >> crc; unpacked >> unknown; // Hacky fix, Yea I know its a hacky fix I will make a proper handler one's I got the crc crap if (crc != 0x4C1C776D) // CRC of public key version 2.0.1 returnpacket.append(PublicKey,264); // part of the hacky fix else returnpacket << uint8(0x02) << uint8(0x01) << uint8(0x00) << uint32(0) << uint8(0); /*if(!AppendPublicKey(returnpacket, name, crc)) returnpacket << uint8(1) << uint8(0) << uint8(0);*/ } uint32 unk308; unpacked >> unk308; m_session->SendPacket(&returnpacket); }
void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) { if(!GetPlayer()->isAlive()) return; if (!GetPlayer()->CanSpeak()) { std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); return; } CHECK_PACKET_SIZE(recv_data,4+4+8); uint32 text_emote, emoteNum; uint64 guid; recv_data >> text_emote; recv_data >> emoteNum; recv_data >> guid; const char *nam = 0; uint32 namlen = 1; Unit* unit = ObjectAccessor::GetUnit(*_player, guid); Creature *pCreature = dynamic_cast<Creature *>(unit); if(unit) { nam = unit->GetName(); namlen = (nam ? strlen(nam) : 0) + 1; } EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); if (em) { uint32 emote_anim = em->textid; WorldPacket data; switch(emote_anim) { case EMOTE_STATE_SLEEP: case EMOTE_STATE_SIT: case EMOTE_STATE_KNEEL: case EMOTE_ONESHOT_NONE: break; default: GetPlayer()->HandleEmoteCommand(emote_anim); break; } data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); data << GetPlayer()->GetGUID(); data << (uint32)text_emote; data << emoteNum; data << (uint32)namlen; if( namlen > 1 ) { data.append(nam, namlen); } else { data << (uint8)0x00; } GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); //Send scripted event call if (pCreature && Script) Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); } }
bool WorldSocket::ProcessIncomingData() { ClientPktHeader header; if (m_useExistingHeader) { m_useExistingHeader = false; header = m_existingHeader; ReadSkip(sizeof(ClientPktHeader)); } else { if (!Read((char *)&header, sizeof(ClientPktHeader))) { errno = EBADMSG; return false; } m_crypt.DecryptRecv((uint8 *)&header, sizeof(ClientPktHeader)); EndianConvertReverse(header.size); EndianConvert(header.cmd); } // there must always be at least four bytes for the opcode, // and 0x2800 is the largest supported buffer in the client if ((header.size < 4) || (header.size > 0x2800) || (header.cmd >= NUM_MSG_TYPES)) { sLog.outError("WorldSocket::ProcessIncomingData: client sent malformed packet size = %u , cmd = %u", header.size, header.cmd); errno = EINVAL; return false; } // the minus four is because we've already read the four byte opcode value const uint16 validBytesRemaining = header.size - 4; // check if the client has told us that there is more data than there is if (validBytesRemaining > ReadLengthRemaining()) { // we must preserve the decrypted header so as not to corrupt the crypto state, and to prevent duplicating work m_useExistingHeader = true; m_existingHeader = header; // we move the read pointer backward because it will be skipped again later. this is a slight kludge, but to solve // it more elegantly would require introducing protocol awareness into the socket library, which we want to avoid ReadSkip(-static_cast<int>(sizeof(ClientPktHeader))); errno = EBADMSG; return false; } const Opcodes opcode = static_cast<Opcodes>(header.cmd); if (IsClosed()) return false; // Dump received packet. //sLog.outWorldPacketDump(uint32(get_handle()), new_pct->GetOpcode(), new_pct->GetOpcodeName(), new_pct, true); WorldPacket *pct = new WorldPacket(opcode, validBytesRemaining); if (validBytesRemaining) { pct->append(InPeak(), validBytesRemaining); ReadSkip(validBytesRemaining); } try { switch (opcode) { case CMSG_AUTH_SESSION: if (m_session) { sLog.outError("WorldSocket::ProcessIncomingData: Player send CMSG_AUTH_SESSION again"); return false; } return HandleAuthSession(*pct); case CMSG_PING: return HandlePing(*pct); case CMSG_KEEP_ALIVE: DEBUG_LOG("CMSG_KEEP_ALIVE ,size: " SIZEFMTD " ", pct->size()); return true; default: { if (!m_session) { sLog.outError("WorldSocket::ProcessIncomingData: Client not authed opcode = %u", uint32(opcode)); return false; } m_session->QueuePacket(pct); return true; } } } catch (ByteBufferException&) { sLog.outError("WorldSocket::ProcessIncomingData ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i.", opcode, GetRemoteAddress().c_str(), m_session ? m_session->GetAccountId() : -1); if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) { DEBUG_LOG("Dumping error-causing packet:"); pct->hexlike(); } if (sWorld.getConfig(CONFIG_BOOL_KICK_PLAYER_ON_BAD_PACKET)) { DETAIL_LOG("Disconnecting session [account id %i / address %s] for badly formatted packet.", m_session ? m_session->GetAccountId() : -1, GetRemoteAddress().c_str()); return false; } } return true; }
void AddonMgr::SendAddonInfoPacket(WorldPacket *source, uint32 pos, WorldSession *m_session) { WorldPacket returnpacket; returnpacket.Initialize(SMSG_ADDON_INFO); // SMSG_ADDON_INFO uint32 realsize; uLongf rsize; try { *source >> realsize; } catch (ByteBuffer::error &) { OUT_DEBUG("Warning: Incomplete auth session sent."); return; } rsize = realsize; size_t position = source->rpos(); ByteBuffer unpacked; unpacked.resize(realsize); if((source->size() - position) < 4 || realsize == 0) { // we shouldnt get here.. but just in case this will stop any crash here. OUT_DEBUG("Warning: Incomplete auth session sent."); return; } int32 result; result = uncompress((uint8*)unpacked.contents(), &rsize, (uint8*)(*source).contents() + position, (uLong)((*source).size() - position)); if(result != Z_OK) { OUT_DEBUG("Decompression of addon section of CMSG_AUTH_SESSION failed."); return; } OUT_DEBUG("Decompression of addon section of CMSG_AUTH_SESSION succeeded."); uint32 addons; uint8 Enable; // based on the parsed files from retool uint32 crc; uint32 unknown; unpacked >> addons; size_t p = unpacked.rpos(); if( p + (addons*10) > unpacked.size() - p - 4) { // stupid f****r, trying to make us waste CPU cycles m_session->Disconnect(); return; } std::string name; //size_t p = unpacked.rpos(); { uint8 unk; uint8 unk1; uint8 unk2; uint32 unk3; for(uint32 i = 0; i < addons; ++i) { unpacked >> name; unpacked >> Enable; unpacked >> crc; unpacked >> unknown; unk = (Enable ? 2 : 1); returnpacket << unk; unk1 = (Enable ? 1 : 0); returnpacket << unk1; if (unk1) { if(crc != 0x4C1C776D) { returnpacket << uint8(1); returnpacket.append(PublicKey,264); } else returnpacket << uint8(0); returnpacket << uint32(0); } unk2 = (Enable ? 0 : 1); returnpacket << unk2; if (unk2) returnpacket << uint8(0); //p = unpacked.rpos(); } unpacked >> unk3; //Added in 3.0.8 } m_session->SendPacket(&returnpacket); }
void AddonMgr::SendAddonInfoPacket(WorldPacket* source, uint32 pos, WorldSession* m_session) { WorldPacket returnpacket; returnpacket.Initialize(SMSG_ADDON_INFO); // SMSG_ADDON_INFO uint32 realsize; uLongf rsize; try { *source >> realsize; } catch(ByteBuffer::error &) { LOG_DEBUG("Warning: Incomplete auth session sent."); return; } rsize = realsize; size_t position = source->rpos(); ByteBuffer unpacked; unpacked.resize(realsize); if((source->size() - position) < 4 || realsize == 0) { // we shouldn't get here.. but just in case this will stop any crash here. LOG_DEBUG("Warning: Incomplete auth session sent."); return; } int32 result = uncompress((uint8*)unpacked.contents(), &rsize, (uint8*)(*source).contents() + position, (uLong)((*source).size() - position)); if(result != Z_OK) { LOG_ERROR("Decompression of addon section of CMSG_AUTH_SESSION failed."); return; } LOG_DETAIL("Decompression of addon section of CMSG_AUTH_SESSION succeeded."); uint8 Enable; // based on the parsed files from retool uint32 crc; uint32 unknown; std::string name; uint32 addoncount; unpacked >> addoncount; uint8 unk; uint8 unk1; uint8 unk2; for(uint32 i = 0; i < addoncount; ++i) { if(unpacked.rpos() >= unpacked.size()) break; unpacked >> name; unpacked >> Enable; unpacked >> crc; unpacked >> unknown; // Hacky fix, Yea I know its a hacky fix I will make a proper handler one's I got the crc crap /* if (crc != 0x4C1C776D) // CRC of public key version 2.0.1 returnpacket.append(PublicKey,264); // part of the hacky fix else returnpacket << uint8(0x02) << uint8(0x01) << uint8(0x00) << uint32(0) << uint8(0);*/ /*if(!AppendPublicKey(returnpacket, name, crc)) returnpacket << uint8(1) << uint8(0) << uint8(0);*/ unk = (Enable ? 2 : 1); returnpacket << unk; unk1 = (Enable ? 1 : 0); returnpacket << unk1; if(unk1) { if(crc != 0x4C1C776D) { returnpacket << uint8(1); returnpacket.append(PublicKey, 264); } else returnpacket << uint8(0); returnpacket << uint32(0); } unk2 = (Enable ? 0 : 1); returnpacket << unk2; if(unk2) returnpacket << uint8(0); } /*unknown 4 bytes at the end of the packet. Stays 0 for me. Tried custom addons, deleting, faulty etc. It stays 0. */ returnpacket << uint32(0); //Some additional count for additional records, but we won't send them. m_session->SendPacket(&returnpacket); }