bool ChatHandler::HandleDebugSendOpcodeCommand(char* /*args*/) { Unit* unit = getSelectedUnit(); if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) unit = m_session->GetPlayer(); std::ifstream ifs("opcode.txt"); if (ifs.bad()) return false; uint32 opcode; ifs >> opcode; WorldPacket data(Opcodes(opcode), 0); while (!ifs.eof()) { std::string type; ifs >> type; if (type == "") break; if (type == "uint8") { uint16 val1; ifs >> val1; data << uint8(val1); } else if (type == "uint16")
static bool HandleDebugSendOpcodeCommand(ChatHandler* handler, const char* /*args*/) { Unit* unit = handler->getSelectedUnit(); Player* player = NULL; if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) player = handler->GetSession()->GetPlayer(); else player = (Player*)unit; if (!unit) unit = player; std::ifstream ifs("opcode.txt"); if (ifs.bad()) return false; uint32 opcode; ifs >> opcode; WorldPacket data(Opcodes(opcode), 0); while (!ifs.eof()) { std::string type; ifs >> type; if (type == "") break; if (type == "uint8") { uint16 val1; ifs >> val1; data << uint8(val1); } else if (type == "uint16")
//! Compresses another packet and stores it in self (source left intact) void WorldPacket::Compress(z_stream* compressionStream, WorldPacket const* source) { ASSERT(source != this); Opcodes uncompressedOpcode = source->GetOpcode(); if (uncompressedOpcode & COMPRESSED_OPCODE_MASK) { sLog->outError(LOG_FILTER_NETWORKIO, "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode); return; } Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK); uint32 size = source->size(); uint32 destsize = compressBound(size); size_t sizePos = 0; resize(destsize + sizeof(uint32)); _compressionStream = compressionStream; Compress(static_cast<void*>(&_storage[0] + sizeof(uint32)), &destsize, static_cast<const void*>(source->contents()), size); if (destsize == 0) return; put<uint32>(sizePos, size); resize(destsize + sizeof(uint32)); SetOpcode(opcode); sLog->outInfo(LOG_FILTER_NETWORKIO, "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode, true).c_str(), size, opcode, destsize); }
//! Compresses packet in place void WorldPacket::Compress(z_stream* compressionStream) { Opcodes uncompressedOpcode = GetOpcode(); if (uncompressedOpcode & COMPRESSED_OPCODE_MASK) { sLog->outError(LOG_FILTER_NETWORKIO, "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode); return; } Opcodes opcode = Opcodes(uncompressedOpcode | COMPRESSED_OPCODE_MASK); uint32 size = wpos(); uint32 destsize = compressBound(size); std::vector<uint8> storage(destsize); _compressionStream = compressionStream; Compress(static_cast<void*>(&storage[0]), &destsize, static_cast<const void*>(contents()), size); if (destsize == 0) return; clear(); reserve(destsize + sizeof(uint32)); *this << uint32(size); append(&storage[0], destsize); SetOpcode(opcode); sLog->outInfo(LOG_FILTER_NETWORKIO, "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode, true).c_str(), size, opcode, destsize); }
int WorldSocket::handle_input_header (void) { ACE_ASSERT(m_RecvWPct == NULL); if (m_Crypt.IsInitialized()) { uint8* clientHeader = (uint8*)m_WorldHeader.rd_ptr(); WorldClientPktHeader& header = *((WorldClientPktHeader*)clientHeader); m_Crypt.DecryptRecv(clientHeader, 4); uint32 value = *(uint32*)clientHeader; uint32 opcode = value & 0xFFF; uint16 size = (uint16)((value & ~(uint32)0xFFF) >> 12); header.size = size + 4; header.cmd = opcode; if ((header.size < 4) || (header.size > 10240) || (header.cmd >= 0xFFFF)) { sLog->outError(LOG_FILTER_GENERAL,"WorldSocket::handle_input_header: client sent malformed packet size = %d , cmd = %d", header.size, header.cmd); errno = EINVAL; return -1; } header.size -= 4; ACE_NEW_RETURN(m_RecvWPct, WorldPacket (PacketFilter::DropHighBytes(Opcodes(header.cmd)), header.size), -1); if (header.size > 0) { m_RecvWPct->resize(header.size); m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size()); } else { ACE_ASSERT(m_RecvPct.space() == 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(Opcodes(recvPacket.read<uint32>())); HandleMovementOpcodes(recvPacket); } }
int WorldSocket::handle_input_header (void) { ACE_ASSERT(m_RecvWPct == NULL); if (m_Crypt.IsInitialized()) { ACE_ASSERT(m_WorldHeader.length() == sizeof(WorldClientPktHeader)); uint8* uintHeader = (uint8*)m_WorldHeader.rd_ptr(); m_Crypt.DecryptRecv(uintHeader, sizeof(WorldClientPktHeader)); WorldClientPktHeader& header = *(WorldClientPktHeader*)uintHeader; uint32 value = *(uint32*)uintHeader; header.cmd = value & 0x1FFF; header.size = ((value & ~(uint32)0x1FFF) >> 13); if (header.size > 10236) { Player* _player = m_Session ? m_Session->GetPlayer() : NULL; TC_LOG_ERROR("network", "WorldSocket::handle_input_header(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %d, cmd: %d)", m_Session ? m_Session->GetAccountId() : 0, _player ? _player->GetGUIDLow() : 0, _player ? _player->GetName().c_str() : "<none>", header.size, header.cmd); errno = EINVAL; return -1; } ACE_NEW_RETURN(m_RecvWPct, WorldPacket (PacketFilter::DropHighBytes(Opcodes(header.cmd)), header.size), -1); if (header.size > 0) { m_RecvWPct->resize(header.size); m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size()); } else ACE_ASSERT(m_RecvPct.space() == 0); }
int WorldSocket::handle_input_header(void) { MANGOS_ASSERT(m_RecvWPct == NULL); MANGOS_ASSERT(m_Header.length() == sizeof(ClientPktHeader)); m_Crypt.DecryptRecv((uint8*) m_Header.rd_ptr(), sizeof(ClientPktHeader)); ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr()); EndianConvertReverse(header.size); EndianConvert(header.cmd); if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240)) { sLog.outError("WorldSocket::handle_input_header: client sent malformed packet size = %d , cmd = %d", header.size, header.cmd); errno = EINVAL; return -1; } header.size -= 4; ACE_NEW_RETURN(m_RecvWPct, WorldPacket(Opcodes(header.cmd), header.size), -1); if (header.size > 0) { m_RecvWPct->resize(header.size); m_RecvPct.base((char*) m_RecvWPct->contents(), m_RecvWPct->size()); } else { MANGOS_ASSERT(m_RecvPct.space() == 0); } return 0; }
static bool HandleDebugSendOpcodeCommand(ChatHandler* handler, const char* /*args*/) { Unit* unit = handler->getSelectedUnit(); Player* player = NULL; if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) player = handler->GetSession()->GetPlayer(); else player = (Player*)unit; if (!unit) unit = player; std::ifstream ifs("opcode.txt"); if (ifs.bad()) return false; // remove comments from file std::stringstream parsedStream; while (!ifs.eof()) { char commentToken[2]; ifs.get(commentToken[0]); if (commentToken[0] == '/' && !ifs.eof()) { ifs.get(commentToken[1]); // /* comment if (commentToken[1] == '*') { while (!ifs.eof()) { ifs.get(commentToken[0]); if (commentToken[0] == '*' && !ifs.eof()) { ifs.get(commentToken[1]); if (commentToken[1] == '/') break; else ifs.putback(commentToken[1]); } } continue; } // line comment else if (commentToken[1] == '/') { std::string str; getline(ifs,str); continue; } // regular data else { ifs.putback(commentToken[1]); } } parsedStream.put(commentToken[0]); } ifs.close(); uint32 opcode; parsedStream >> opcode; WorldPacket data(Opcodes(opcode), 0); while (!parsedStream.eof()) { std::string type; parsedStream >> type; if (type == "") break; if (type == "uint8") { uint16 val1; parsedStream >> val1; data << uint8(val1); } else if (type == "uint16")
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { Opcodes opcode = recv_data.GetOpcodeEnum(); DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); recv_data.hexlike(); Unit *mover = _player->m_mover; STRAWBERRY_ASSERT(mover != NULL); // there must always be a mover Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plMover && plMover->IsBeingTeleported()) { recv_data.rfinish(); // prevent warnings spam return; } /* extract packet */ MovementInfo movementInfo; ReadMovementInfo(recv_data, &movementInfo); recv_data.rfinish(); // prevent warnings spam // prevent tampered movement data if (movementInfo.guid != mover->GetObjectGuid()) return; /* handle special cases */ if (movementInfo.moveFlags & MOVEFLAG_ONTRANSPORT) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if (movementInfo.t_pos.x > 50 || movementInfo.t_pos.y > 50 || movementInfo.t_pos.z > 50) { recv_data.rfinish(); // prevent warnings spam return; } if (!Strawberry::IsValidMapCoord(movementInfo.pos.x + movementInfo.t_pos.x, movementInfo.pos.y + movementInfo.t_pos.y), movementInfo.pos.z + movementInfo.t_pos.z, movementInfo.pos.o + movementInfo.t_pos.o) { recv_data.rfinish(); // prevent warnings spam return; } // if we boarded a transport, add us to it if (plMover && !plMover->GetTransport()) { // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter) { if ((*iter)->GetObjectGuid() == movementInfo.t_guid) { plMover->m_transport = (*iter); (*iter)->AddPassenger(plMover); break; } } } if (!mover->GetTransport() && !mover->GetVehicle()) { GameObject *go = mover->GetMap()->GetGameObject(movementInfo.t_guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) movementInfo.moveFlags &= ~MOVEFLAG_ONTRANSPORT; } } else if (plMover && plMover->GetTransport()) // if we were on a transport, leave { plMover->m_transport->RemovePassenger(plMover); plMover->m_transport = NULL; movementInfo.t_time = 0; movementInfo.t_seat = -1; } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == MSG_MOVE_FALL_LAND && plMover) plMover->HandleFall(movementInfo); if (plMover && ((movementInfo.moveFlags & MOVEFLAG_SWIMMING) != 0) != plMover->IsInWater()) { // now client not include swimming flag in case jumping under water plMover->SetInWater(!plMover->IsInWater());// || plMover->GetMap()->IsUnderWater(movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.y)); } /*----------------------*/ /* process position-change */ WorldPacket data(Opcodes(opcode), recv_data.size()); movementInfo.time = WorldTimer::getMSTime(); movementInfo.guid = mover->GetObjectGuid(); WriteMovementInfo(&data, &movementInfo); mover->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() if (mover->GetVehicle()) { mover->SetOrientation(movementInfo.pos.o); return; } mover->SetPosition(movementInfo.pos.x, movementInfo.pos.y, movementInfo.pos.z, movementInfo.pos.o, false); if (plMover) // nothing is charmed, or player charmed { plMover->UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.pos.z < -500.0f) { //if (!(plMover->InBattleground() // && plMover->GetBattleground() // && plMover->GetBattleground()->HandlePlayerUnderMap(_player))) { // NOTE: this is actually called many times while falling // even after the player has been teleported away // TODO: discard movement packets after the player is rooted if (plMover->isAlive()) { plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // pl can be alive if GM/etc if (!plMover->isAlive()) { // change the death state to CORPSE to prevent the death timer from // starting in the next player update plMover->KillPlayer(); plMover->BuildPlayerRepop(); } } // cancel the death timer here if started //plMover->RepopAtGraveyard(); } } } }
bool WorldSession::HandleMovementInfo(MovementInfo &movementInfo, const uint16 opcode, const size_t packSize, Unit *mover) { ASSERT(mover != NULL); if (movementInfo.guid != mover->GetGUID() || !movementInfo.pos.IsPositionValid()) return false; Player* plrMover = mover->ToPlayer(); if (plrMover && plrMover->IsBeingTeleported()) return false; if (plrMover && plrMover->HasUnitState(UNIT_STATE_CONTROLLED_BY_SERVER) && !CanMovementBeProcessed(opcode)) return false; movementInfo.Sanitize(mover); if (movementInfo.t_guid) { if (movementInfo.t_pos.GetPositionX() > 50.0f || movementInfo.t_pos.GetPositionY() > 50.0f || movementInfo.t_pos.GetPositionZ() > 50.0f) return false; // moved out of transport size if (!Trinity::IsValidMapCoord( movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(), movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation()) ) return false; // just bad coords if (plrMover) { if (!plrMover->GetTransport()) // didn't have transport. now have { for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.t_guid) { plrMover->m_transport = *iter; (*iter)->AddPassenger(plrMover); break; } } } else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid) // changes transport { bool foundNewTransport = false; plrMover->m_transport->RemovePassenger(plrMover); for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { if ((*iter)->GetGUID() == movementInfo.t_guid) { foundNewTransport = true; plrMover->m_transport = *iter; (*iter)->AddPassenger(plrMover); break; } } if (!foundNewTransport) { plrMover->m_transport = NULL; movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); movementInfo.t_time = 0; movementInfo.t_seat = -1; } } else if (movementInfo.pos.m_positionX != movementInfo.t_pos.m_positionX) plrMover->GetTransport()->UpdatePosition(&movementInfo); } if (!mover->GetTransport() && !mover->GetVehicle()) { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) movementInfo.t_guid = 0; } } else if (plrMover && plrMover->GetTransport()) // had transport, no loger have { plrMover->m_transport->RemovePassenger(plrMover); plrMover->m_transport = NULL; movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); movementInfo.t_time = 0; movementInfo.t_seat = -1; } if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->isInFlight()) plrMover->HandleFall(movementInfo); if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } if (plrMover) sAnticheatMgr->StartHackDetection(plrMover, movementInfo, opcode); WorldPacket data(movementInfo.GetSMSGOpcodeForCMSG(Opcodes(opcode)), packSize); movementInfo.time = getMSTime(); movementInfo.guid = mover->GetGUID(); movementInfo.WriteToPacket(data); _player->SendMessageToSet(&data, _player); mover->m_movementInfo = movementInfo; if (mover->GetVehicle()) // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() { mover->SetOrientation(movementInfo.pos.GetOrientation()); return true; } // Remove pet when starting to fly if (plrMover && plrMover->IsFlying()) plrMover->UnsummonPetTemporaryIfAny(); mover->UpdatePosition(movementInfo.pos); if (plrMover) { plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); float underMapValueZ, upperLimitValueZ; bool check = false; switch (plrMover->GetMapId()) { case 617: // Dalaran Arena underMapValueZ = 3.0f; upperLimitValueZ = 30.0f; break; case 562: // Blades Edge Arena underMapValueZ = -1.0f; upperLimitValueZ = 22.0f; break; case 559: // Nagrand Arena underMapValueZ = -1.0f; upperLimitValueZ = 21.0f; break; case 572: // Ruins of Lordaeron underMapValueZ = -1.0f; upperLimitValueZ = 45.0f; break; case 618: // Ring of Valor underMapValueZ = 28.0f; upperLimitValueZ = 60.0f; break; case 566: // Eye of the storm underMapValueZ = 1000.0f; upperLimitValueZ = MAX_HEIGHT; break; default: AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId()); underMapValueZ = zone ? zone->MaxDepth : -500.0f; upperLimitValueZ = MAX_HEIGHT; break; } check = movementInfo.pos.GetPositionZ() < underMapValueZ || movementInfo.pos.GetPositionZ() > upperLimitValueZ; if (check && plrMover->isAlive() && !(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); if (!plrMover->isAlive()) plrMover->KillPlayer(); // prevent death timer plrMover->RepopAtGraveyard(); } } return true; }