From 1df1f7cff5db38e7747a9044c0dbdd5821bcd16c Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 9 Aug 2009 18:08:14 +0400 Subject: [PATCH] Fixed player movement. Fixed multinode taxi. Removed some unhandled opcode spam. --- src/game/Group.cpp | 4 +-- src/game/ItemHandler.cpp | 27 +++++++++++++++ src/game/ItemPrototype.h | 4 +++ src/game/MovementHandler.cpp | 67 ++++++++++++++++++++++++++++-------- src/game/Opcodes.cpp | 6 ++-- src/game/Opcodes.h | 6 ++-- src/game/TaxiHandler.cpp | 8 ++--- src/game/WorldSession.cpp | 48 ++++++++++++++++++++++++-- src/game/WorldSession.h | 2 ++ 9 files changed, 142 insertions(+), 30 deletions(-) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index 75299c935..3a38909c1 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -109,8 +109,8 @@ bool Group::Create(const uint64 &guid, const char * name) CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM groups WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid)); CharacterDatabase.PExecute("DELETE FROM group_member WHERE leaderGuid ='%u'", GUID_LOPART(m_leaderGuid)); - CharacterDatabase.PExecute("INSERT INTO groups(leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty,raiddifficulty) " - "VALUES('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u')", + CharacterDatabase.PExecute("INSERT INTO groups (leaderGuid,mainTank,mainAssistant,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,isRaid,difficulty,raiddifficulty) " + "VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')", GUID_LOPART(m_leaderGuid), GUID_LOPART(m_mainTank), GUID_LOPART(m_mainAssistant), uint32(m_lootMethod), GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], isRaidGroup(), m_dungeonDifficulty, m_raidDifficulty); } diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index ec9a285d8..692464cf6 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -1378,3 +1378,30 @@ void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data) GetPlayer()->ApplyEnchantment(item, TEMP_ENCHANTMENT_SLOT, false); item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); } + +void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: CMSG_ITEM_REFUND_INFO_REQUEST"); + + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + + recv_data >> guid; // item guid + + Item *item = _player->GetItemByGuid(guid); + + if(!item) + { + sLog.outDebug("Item refund: item not found!"); + return; + } + + if(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_REFUNDABLE)) + { + sLog.outDebug("Item refund: item not refundable!"); + return; + } + + // refund system not implemented yet +} diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index cfa41ac05..1789752b1 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -109,8 +109,11 @@ enum ITEM_FLAGS ITEM_FLAGS_OPENABLE = 0x00000004, ITEM_FLAGS_WRAPPED = 0x00000008, ITEM_FLAGS_BROKEN = 0x00000010, // appears red icon (like when item durability==0) + ITEM_FLAGS_TOTEM = 0x00000020, // ? + ITEM_FLAGS_USABLE = 0x00000040, // ? ITEM_FLAGS_WRAPPER = 0x00000200, // used or not used wrapper ITEM_FLAGS_PARTY_LOOT = 0x00000800, // determines if item is party loot or not + ITEM_FLAGS_REFUNDABLE = 0x00001000, // item cost can be refunded within 2 hours after purchase ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter ITEM_FLAGS_PROSPECTABLE = 0x00040000, ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000, @@ -118,6 +121,7 @@ enum ITEM_FLAGS ITEM_FLAGS_THROWABLE = 0x00400000, // not used in game for check trow possibility, only for item in game tooltip ITEM_FLAGS_SPECIALUSE = 0x00800000, // last used flag in 2.3.0 ITEM_FLAGS_BOA = 0x08000000, // bind on account (set in template for items that can binded in like way) + ITEM_FLAGS_ENCHANT_SCROLL = 0x10000000, // for enchant scrolls ITEM_FLAGS_MILLABLE = 0x20000000 }; diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index b82295f0b..d541e822a 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -216,20 +216,26 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) recv_data.hexlike(); Unit *mover = _player->m_mover; - Player *plMover = mover->GetTypeId()==TYPEID_PLAYER ? (Player*)mover : NULL; + Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if(plMover && plMover->IsBeingTeleported()) return; /* extract packet */ + uint64 guid; + + if(!recv_data.readPackGUID(guid)) + return; + MovementInfo movementInfo; + movementInfo.guid = guid; ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ if(recv_data.size() != recv_data.rpos()) { - sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); + sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), opcode, recv_data.size() - recv_data.rpos()); KickPlayer(); return; } @@ -289,17 +295,17 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) /*----------------------*/ /* process position-change */ - recv_data.put(6, getMSTime()); // fix time, offset flags(4) + unk(2) - WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size())); - data.append(mover->GetPackGUID()); // use mover guid - data.append(recv_data.contents(), recv_data.size()); + WorldPacket data(opcode, recv_data.size()); + movementInfo.time = getMSTime(); + movementInfo.guid = mover->GetGUID(); + WriteMovementInfo(&data, &movementInfo); GetPlayer()->SendMessageToSet(&data, false); if(plMover) // nothing is charmed, or player charmed { plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); plMover->m_movementInfo = movementInfo; - plMover->UpdateFallInformationIfNeed(movementInfo, recv_data.GetOpcode()); + plMover->UpdateFallInformationIfNeed(movementInfo, opcode); if(plMover->isMovingOrTurning()) plMover->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); @@ -344,26 +350,28 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) { - sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); - - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4); + uint32 opcode = recv_data.GetOpcode(); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); /* extract packet */ uint64 guid; uint32 unk1; float newspeed; - recv_data >> guid; + if(!recv_data.readPackGUID(guid)) + return; // now can skip not our packet if(_player->GetGUID() != guid) return; // continue parse packet + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); recv_data >> unk1; // counter or moveEvent MovementInfo movementInfo; + movementInfo.guid = guid; ReadMovementInfo(recv_data, &movementInfo); // recheck @@ -372,6 +380,13 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) recv_data >> newspeed; /*----------------*/ + if(recv_data.size() != recv_data.rpos()) + { + sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), opcode, recv_data.size() - recv_data.rpos()); + KickPlayer(); + return; + } + // client ACK send one packet for mounted/run case and need skip all except last from its // in other cases anti-cheat check can be fail in false case UnitMoveType move_type; @@ -379,7 +394,6 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; - uint16 opcode = recv_data.GetOpcode(); switch(opcode) { case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; @@ -444,10 +458,10 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); recv_data.hexlike(); - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8); - uint64 old_mover_guid; - recv_data >> old_mover_guid; + + if(!recv_data.readPackGUID(old_mover_guid)) + return; if(_player->m_mover->GetGUID() == old_mover_guid) { @@ -456,7 +470,16 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) } MovementInfo mi; + mi.guid = old_mover_guid; ReadMovementInfo(recv_data, &mi); + + if(recv_data.size() != recv_data.rpos()) + { + sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); + KickPlayer(); + return; + } + _player->m_movementInfo = mi; } @@ -470,8 +493,22 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) if(!vehicleGUID) // something wrong here... return; + uint64 guid; + + if(!recv_data.readPackGUID(guid)) + return; + MovementInfo mi; + mi.guid = guid; ReadMovementInfo(recv_data, &mi); + + if(recv_data.size() != recv_data.rpos()) + { + sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); + KickPlayer(); + return; + } + _player->m_movementInfo = mi; // using charm guid, because we don't have vehicle guid... diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index e2ff8282d..e364bfd22 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1229,7 +1229,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x4B0*/ { "UMSG_UNKNOWN_1200", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4B1*/ { "UMSG_UNKNOWN_1201", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4B2*/ { "SMSG_UNKNOWN_1202", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4B3*/ { "CMSG_UNKNOWN_1203", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4B3*/ { "CMSG_ITEM_REFUND_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleItemRefundInfoRequest }, /*0x4B4*/ { "CMSG_UNKNOWN_1204", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4B5*/ { "SMSG_UNKNOWN_1205", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4B6*/ { "CMSG_UNKNOWN_1206", STATUS_NEVER, &WorldSession::Handle_NULL }, @@ -1257,9 +1257,9 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4CD*/ { "SMSG_UNKNOWN_1229", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4CE*/ { "SMSG_UNKNOWN_1230", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4CF*/ { "UMSG_UNKNOWN_1231", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4CF*/ { "CMSG_UNKNOWN_1231_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4D0*/ { "SMSG_UNKNOWN_1232", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D1*/ { "UMSG_UNKNOWN_1233", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4D1*/ { "CMSG_UNKNOWN_1233_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4D2*/ { "SMSG_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4D3*/ { "SMSG_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4D4*/ { "SMSG_UNKNOWN_1236", STATUS_NEVER, &WorldSession::Handle_ServerSide }, diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 0a6c6b268..a41e833c8 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1237,7 +1237,7 @@ enum Opcodes UMSG_UNKNOWN_1200 = 0x4B0, // not found UMSG_UNKNOWN_1201 = 0x4B1, // not found SMSG_UNKNOWN_1202 = 0x4B2, // refund something - CMSG_UNKNOWN_1203 = 0x4B3, // refund request? + CMSG_ITEM_REFUND_INFO_REQUEST = 0x4B3, // refund request? CMSG_UNKNOWN_1204 = 0x4B4, // lua: ContainerRefundItemPurchase SMSG_UNKNOWN_1205 = 0x4B5, // refund something CMSG_UNKNOWN_1206 = 0x4B6, // CMSG, uint32 @@ -1265,9 +1265,9 @@ enum Opcodes UMSG_UNKNOWN_1228 = 0x4CC, // not found 3.2 SMSG_UNKNOWN_1229 = 0x4CD, // SMSG, any opcode? SMSG_UNKNOWN_1230 = 0x4CE, // SMSG, movement related - UMSG_UNKNOWN_1231 = 0x4CF, // not found 3.2 + CMSG_UNKNOWN_1231_ACK = 0x4CF, // movement related SMSG_UNKNOWN_1232 = 0x4D0, // SMSG, movement related - UMSG_UNKNOWN_1233 = 0x4D1, // not found 3.2 + CMSG_UNKNOWN_1233_ACK = 0x4D1, // movement related SMSG_UNKNOWN_1234 = 0x4D2, // SMSG, movement related SMSG_UNKNOWN_1235 = 0x4D3, // SMSG, movement related SMSG_UNKNOWN_1236 = 0x4D4, // SMSG, movement related diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index fe2f28c3b..b3118aa14 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -158,14 +158,14 @@ bool WorldSession::SendLearnNewTaxiNode( Creature* unit ) void WorldSession::HandleActivateTaxiExpressOpcode ( WorldPacket & recv_data ) { - CHECK_PACKET_SIZE(recv_data,8+4+4); + CHECK_PACKET_SIZE(recv_data,8+4); sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXIEXPRESS" ); uint64 guid; - uint32 node_count, _totalcost; + uint32 node_count; - recv_data >> guid >> _totalcost >> node_count; + recv_data >> guid >> node_count; Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!npc) @@ -174,7 +174,7 @@ void WorldSession::HandleActivateTaxiExpressOpcode ( WorldPacket & recv_data ) return; } // recheck - CHECK_PACKET_SIZE(recv_data,8+4+4+node_count*4); + CHECK_PACKET_SIZE(recv_data,8+4+node_count*4); std::vector nodes; diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index eb16e4d13..a52eec5ef 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -629,9 +629,6 @@ void WorldSession::SaveTutorialsData() void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi) { - if(!data.readPackGUID(mi->guid)) - return; - CHECK_PACKET_SIZE(data, data.rpos()+4+2+4+4+4+4+4); data >> mi->flags; data >> mi->unk1; @@ -680,6 +677,51 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi) } } +void WorldSession::WriteMovementInfo(WorldPacket *data, MovementInfo *mi) +{ + data->appendPackGUID(mi->guid); + + *data << mi->flags; + *data << mi->unk1; + *data << mi->time; + *data << mi->x; + *data << mi->y; + *data << mi->z; + *data << mi->o; + + if(mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + data->appendPackGUID(mi->t_guid); + + *data << mi->t_x; + *data << mi->t_y; + *data << mi->t_z; + *data << mi->t_o; + *data << mi->t_time; + *data << mi->t_seat; + } + + if((mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))) || (mi->unk1 & 0x20)) + { + *data << mi->s_pitch; + } + + *data << mi->fallTime; + + if(mi->HasMovementFlag(MOVEMENTFLAG_JUMPING)) + { + *data << mi->j_unk; + *data << mi->j_sinAngle; + *data << mi->j_cosAngle; + *data << mi->j_xyspeed; + } + + if(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE)) + { + *data << mi->u_unk1; + } +} + void WorldSession::ReadAddonsInfo(WorldPacket &data) { if (data.rpos() + 4 > data.size()) diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index a7fbcadc0..9e916fbf2 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -110,6 +110,7 @@ class MANGOS_DLL_SPEC WorldSession void SendAddonsInfo(); void ReadMovementInfo(WorldPacket &data, MovementInfo *mi); + void WriteMovementInfo(WorldPacket *data, MovementInfo *mi); void SendPacket(WorldPacket const* packet); void SendNotification(const char *format,...) ATTR_PRINTF(2,3); @@ -667,6 +668,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleSocketOpcode(WorldPacket& recv_data); void HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data); + void HandleItemRefundInfoRequest(WorldPacket& recv_data); void HandleChannelVoiceOnOpcode(WorldPacket & recv_data); void HandleVoiceSessionEnableOpcode(WorldPacket& recv_data);