diff --git a/configure.ac b/configure.ac index 1f31c9429..4fc5e6d68 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,9 @@ AC_CONFIG_SRCDIR([src/shared/Base.cpp]) ## Prelude, basic settings for Automake # Turn on all warnings and error messages, and enforce GNU # standards for the package. -AM_INIT_AUTOMAKE([-Wall -Werror gnu tar-pax]) +AM_INIT_AUTOMAKE([foreign -Wall -Werror gnu tar-pax]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + AM_MAINTAINER_MODE ## Prevent the configure script from continuing any further if @@ -69,6 +71,7 @@ AC_PROG_CXX AM_PROG_CC_C_O AC_PROG_LIBTOOL AC_PROG_INSTALL +PKG_PROG_PKG_CONFIG # Check for doxygen AC_ARG_ENABLE(doxygen, AC_HELP_STRING([--enable-doxygen], [turn on generating documentation])) @@ -94,7 +97,7 @@ AC_CHECK_LIB( pthread, pthread_create, [], ]) AC_CHECK_LIB( z, compress, [ZLIB=-lz],[AC_MSG_ERROR([Missing zlib])] ) AC_CHECK_LIB( compat, ftime, [COMPATLIB=-lcompat] ) -AC_CHECK_LIB( crypto, SHA1_Init, [SSLLIB=-lssl], [AC_MSG_ERROR([Missing openssl])]) +PKG_CHECK_MODULES(OPENSSL, [openssl], [], [AC_MSG_ERROR([Missing openssl])]) AC_ARG_WITH(postgresql, [ --with-postgresql Use PostgreSQL as a backend (default: no)], @@ -121,7 +124,7 @@ AC_MSG_CHECKING(whether to build/link POSTGRESQL) if test "x$DO_POSTGRESQL" = "xyes"; then DO_MYSQL=no POSTGRE_INCLUDES="-I/usr/include/postgresql $POSTGRE_INCLUDES" -POSTGRE_LIBS="-L/usr/lib/postresql -lpq -lz -lpthread -lcrypt -lnsl -lm -lpthread -L/usr/lib -lssl -lcrypto $POSTGRE_LIBS " +POSTGRE_LIBS="-L/usr/lib/postresql -lpq -lz -lpthread -lcrypt -lnsl -lm -lpthread -L/usr/lib $OPENSSL_LIBS $POSTGRE_LIBS " CXXFLAGS="-DDO_POSTGRESQL $CXXFLAGS" fi AC_MSG_RESULT($DO_POSTGRESQL) @@ -174,7 +177,6 @@ AC_HEADER_DIRENT AC_CHECK_HEADERS([ arpa/inet.h fcntl.h limits.h locale.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/socket.h sys/timeb.h sys/time.h termios.h unistd.h ]) AC_CHECK_HEADERS([pthread.h]) -AC_CHECK_HEADERS([openssl/md5.h openssl/rand.h openssl/ssl.h openssl/sha.h openssl/bn.h]) AC_CHECK_HEADERS([mysql.h mysql/mysql.h]) AC_CHECK_HEADERS([libpq-fe.h]) AC_CHECK_HEADERS([zlib.h]) @@ -199,36 +201,10 @@ AC_TYPE_SIGNAL AC_FUNC_VPRINTF AC_CHECK_FUNCS([atexit ftime gethostbyaddr gethostbyname gethostname gettimeofday memmove memset pow realpath select socket sqrt strchr strdup strerror strstr]) -## Check what to do with ACE library -AC_LANG_PUSH([C++]) -AC_CHECK_HEADER([ace/Reactor.h], [have_ace_headers=yes], [have_ace_headers=no]) -AC_CHECK_LIB([ACE], [main], [have_ace_lib=yes], [have_ace_lib=no]) -AC_LANG_POP([C++]) - -AC_MSG_CHECKING([whether to build ACE]) -if test X$have_ace_headers = Xyes -a X$have_ace_lib = Xyes; -then - need_to_build_ace=no - AC_MSG_RESULT([no]) -else - if test X$have_ace_headers = Xno -a X$have_ace_lib = Xno; then - need_to_build_ace=yes - AC_MSG_RESULT([yes]) - else - if test X$have_ace_headers = Xyes; then - AC_MSG_ERROR([looks like you have ACE headers, but you do not have ACE libs installed]) - else - need_to_build_ace=yes - AC_MSG_RESULT([yes, over-install]) - fi - fi -fi - -if test X$need_to_build_ace = Xyes; then - MANGOS_INCLUDES="-I\$(top_srcdir)/dep/ACE_wrappers -I\$(top_builddir)/dep/ACE_wrappers $MANGOS_INCLUDES" - MANGOS_LIBS="\$(top_builddir)/dep/ACE_wrappers/ace/libACE.la $MANGOS_LIBS" -else - MANGOS_LIBS="-lACE $MANGOS_LIBS" +PKG_CHECK_MODULES(ACE, [ACE >= 5.5.2], [need_to_build_ace=no], [need_to_build_ace=yes]) +if test X$need_to_build_ace = Xyes ; then + ACE_INCLUDES="-I\$(top_srcdir)/dep/ACE_wrappers -I\$(top_builddir)/dep/ACE_wrappers" + ACE_LIBS="\$(top_builddir)/dep/ACE_wrappers/ace/libACE.la" fi AM_CONDITIONAL([MANGOS_BUILD_ACE], [test X$need_to_build_ace = Xyes]) @@ -238,8 +214,8 @@ AC_CHECK_HEADERS([ace/Stack_Trace.h]) ## Unify all additional includes/libs in one variable. # TODO this looks kinda ugly, but when we add m4 folder I will make it look very pritey ( by Derex ). -MANGOS_INCLUDES="$POSTGRE_INCLUDES $MYSQL_INCLUDES $MANGOS_INCLUDES" -MANGOS_LIBS="$POSTGRE_LIBS $MYSQL_LIBS $ZLIB $COMPATLIB $SSLLIB $MANGOS_LIBS" +MANGOS_INCLUDES="$ACE_INCLUDES $POSTGRE_INCLUDES $MYSQL_INCLUDES $OPENSSL_INCLUDES $MANGOS_INCLUDES" +MANGOS_LIBS="$ACE_LIBS $POSTGRE_LIBS $MYSQL_LIBS $ZLIB $COMPATLIB $OPENSSL_LIBS $MANGOS_LIBS" ## Export defined variables AC_SUBST(DOXYGEN) diff --git a/sql/mangos.sql b/sql/mangos.sql index 9e22461ab..415bef0d3 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8377_01_mangos_spell_area` bit(1) default NULL + `required_8394_01_mangos_spell_proc_event` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -14413,6 +14413,9 @@ INSERT INTO spell_chain VALUES (63625,0,63625,1,0), (63626,63625,63625,2,0), (63627,63626,63625,3,0), +/*Improved Shadowform*/ +(47569,0,47569,1,0), +(47570,47569,47569,2,0), /*Mind Blast*/ (8092,0,8092,1,0), (8102,8092,8092,2,0), @@ -17727,6 +17730,7 @@ INSERT INTO `spell_proc_event` VALUES (47515, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (47516, 0x00000000, 6, 0x00001800, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (47517, 0x00000000, 6, 0x00001800, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(47569, 0x00000000, 6, 0x00004000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), (47580, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), (47581, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), (47582, 0x00000000, 6, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), @@ -17865,6 +17869,7 @@ INSERT INTO `spell_proc_event` VALUES (54488, 0x00000000, 0, 0x20000021, 0x00009000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (54489, 0x00000000, 0, 0x20000021, 0x00009000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (54490, 0x00000000, 0, 0x20000021, 0x00009000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(54646, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00015400, 0x00000002, 0.000000, 0.000000, 0), (54738, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (54747, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), (54749, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), diff --git a/sql/updates/8392_01_mangos_spell_proc_event.sql b/sql/updates/8392_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..39a7cc17b --- /dev/null +++ b/sql/updates/8392_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8377_01_mangos_spell_area required_8392_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (47569); +INSERT INTO `spell_proc_event` VALUES +(47569, 0x00000000, 6, 0x00004000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0); diff --git a/sql/updates/8392_02_mangos_spell_chain.sql b/sql/updates/8392_02_mangos_spell_chain.sql new file mode 100644 index 000000000..efab4d1ea --- /dev/null +++ b/sql/updates/8392_02_mangos_spell_chain.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_8392_01_mangos_spell_proc_event required_8392_02_mangos_spell_chain bit; + +DELETE FROM `spell_chain` WHERE `spell_id` IN (47569,47570); +INSERT INTO `spell_chain` (`spell_id`, `prev_spell`, `first_spell`, `rank`, `req_spell`) VALUES +/*Improved Shadowform*/ +(47569,0,47569,1,0), +(47570,47569,47569,2,0); diff --git a/sql/updates/8394_01_mangos_spell_proc_event.sql b/sql/updates/8394_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..73afa3da5 --- /dev/null +++ b/sql/updates/8394_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8392_02_mangos_spell_chain required_8394_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (54646); +INSERT INTO `spell_proc_event` VALUES +(54646, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00015400, 0x00000002, 0.000000, 0.000000, 0); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index f25b2401f..71168d47d 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -83,6 +83,9 @@ pkgdata_DATA = \ 8361_01_mangos_spell_bonus_data.sql \ 8364_01_mangos_db_version.sql \ 8377_01_mangos_spell_area.sql \ + 8392_01_mangos_spell_proc_event.sql \ + 8392_02_mangos_spell_chain.sql \ + 8394_01_mangos_spell_proc_event.sql \ README ## Additional files to include when running 'make dist' @@ -146,4 +149,7 @@ EXTRA_DIST = \ 8361_01_mangos_spell_bonus_data.sql \ 8364_01_mangos_db_version.sql \ 8377_01_mangos_spell_area.sql \ + 8392_01_mangos_spell_proc_event.sql \ + 8392_02_mangos_spell_chain.sql \ + 8394_01_mangos_spell_proc_event.sql \ README diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp index d1ccc19f3..80b3dee84 100644 --- a/src/game/AuctionHouseHandler.cpp +++ b/src/game/AuctionHouseHandler.cpp @@ -576,6 +576,8 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; recv_data >> quality >> usable; + recv_data.read_skip(16); // unknown 16 bytes: 00 07 01 00 00 01 05 00 06 00 09 01 08 00 03 00 + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { @@ -618,7 +620,8 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data ) { sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES"); - recv_data.hexlike(); + + recv_data.read_skip(); // auctioner guid uint32 count = 0; diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp index 450b5ad41..c5287a767 100644 --- a/src/game/CalendarHandler.cpp +++ b/src/game/CalendarHandler.cpp @@ -96,6 +96,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //std::string unk1, unk2; //recv_data >> (std::string)unk1; @@ -131,6 +132,7 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -149,6 +151,7 @@ void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -160,6 +163,7 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -171,6 +175,7 @@ void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -184,6 +189,7 @@ void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -195,6 +201,7 @@ void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data.readPackGUID(guid) //recv_data >> uint64 @@ -206,6 +213,7 @@ void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data.readPackGUID(guid) //recv_data >> uint64 @@ -218,6 +226,7 @@ void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data.readPackGUID(guid) //recv_data >> uint64 @@ -230,6 +239,7 @@ void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 diff --git a/src/game/GMTicketHandler.cpp b/src/game/GMTicketHandler.cpp index b046a69c8..ffdfae504 100644 --- a/src/game/GMTicketHandler.cpp +++ b/src/game/GMTicketHandler.cpp @@ -84,15 +84,15 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data ) uint32 map; float x, y, z; std::string ticketText = ""; - uint32 unk1, unk2; recv_data >> map >> x >> y >> z; // last check 2.4.3 recv_data >> ticketText; - recv_data >> unk1 >> unk2; - // note: the packet might contain more data, but the exact structure of that is unknown + recv_data.read_skip(); // unk1, 0 + recv_data.read_skip(); // unk2, 1 + recv_data.read_skip(); // unk3, 0 - sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s, unk1 %u, unk2 %u", map, x, y, z, ticketText.c_str(), unk1, unk2); + sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s", map, x, y, z, ticketText.c_str()); if(ticketmgr.GetGMTicket(GetPlayer()->GetGUIDLow())) { diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index b950a80eb..393b8a08f 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -614,12 +614,14 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if(!guild) { + recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } else if(GetPlayer()->GetGUID() != guild->GetLeader()) { + recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } @@ -1026,9 +1028,14 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) uint64 GoGuid; uint8 BankToBank; - uint8 BankTab, BankTabSlot, AutoStore, AutoStoreCount, PlayerSlot, PlayerBag, SplitedAmount = 0; - uint8 BankTabDst, BankTabSlotDst, unk2, ToChar = 1; + uint8 BankTab, BankTabSlot, AutoStore; + uint8 PlayerSlot = NULL_SLOT; + uint8 PlayerBag = NULL_BAG; + uint8 BankTabDst, BankTabSlotDst, unk2; + uint8 ToChar = 1; uint32 ItemEntry, unk1; + uint32 AutoStoreCount = 0; + uint32 SplitedAmount = 0; recv_data >> GoGuid >> BankToBank; if (BankToBank) @@ -1042,10 +1049,11 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) recv_data >> unk2; // always 0 recv_data >> SplitedAmount; - if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS) - return; - if (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) + if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS || BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet return; + } } else { @@ -1056,17 +1064,22 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) if (AutoStore) { recv_data >> AutoStoreCount; + recv_data.read_skip(); // ToChar (?), always and expected to be 1 (autostore only triggered in guild->ToChar) + recv_data.read_skip(); // unknown, always 0 } - recv_data >> PlayerBag; - recv_data >> PlayerSlot; - if (!AutoStore) + else { + recv_data >> PlayerBag; + recv_data >> PlayerSlot; recv_data >> ToChar; recv_data >> SplitedAmount; } if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet return; + } } if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) @@ -1201,14 +1214,6 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) // Player <-> Bank - // char->bank autostore click return BankTabSlot = 255 = NULL_SLOT - // do similar for bank->char - if(AutoStore && ToChar) - { - PlayerBag = NULL_BAG; - PlayerSlot = NULL_SLOT; - } - // allow work with inventory only if(!Player::IsInventoryPos(PlayerBag,PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT) ) { diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 733c196fe..2e9dcd565 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -30,7 +30,8 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) { //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM"); - uint8 srcbag, srcslot, dstbag, dstslot, count; + uint8 srcbag, srcslot, dstbag, dstslot; + uint32 count; recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); @@ -489,12 +490,9 @@ void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data ) { sLog.outDebug( "WORLD: Received CMSG_SELL_ITEM" ); uint64 vendorguid, itemguid; - uint8 _count; + uint32 count; - recv_data >> vendorguid >> itemguid >> _count; - - // prevent possible overflow, as mangos uses uint32 for item count - uint32 count = _count; + recv_data >> vendorguid >> itemguid >> count; if(!itemguid) return; @@ -970,6 +968,8 @@ void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) { uint32 itemid; recv_data >> itemid; + recv_data.read_skip(); // guid + sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid); ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid ); if( pProto ) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 33c7ac9a6..5834c53f0 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -634,7 +634,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) if(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP) > time(NULL)) return; - if (!corpse->IsWithinDist(GetPlayer(),CORPSE_RECLAIM_RADIUS,false)) + if (!corpse->IsWithinDist(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) return; uint64 guid; @@ -721,21 +721,31 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) else { // we have only extent - float dx = pl->GetPositionX() - atEntry->x; - float dy = pl->GetPositionY() - atEntry->y; - float dz = pl->GetPositionZ() - atEntry->z; - double es = sin(atEntry->box_orientation); - double ec = cos(atEntry->box_orientation); - // calc rotated vector based on extent axis - double rotateDx = dx*ec - dy*es; - double rotateDy = dx*es + dy*ec; - if( (fabs(rotateDx) > atEntry->box_x/2 + delta) || - (fabs(rotateDy) > atEntry->box_y/2 + delta) || + // rotate the players position instead of rotating the whole cube, that way we can make a simplified + // is-in-cube check and we have to calculate only one point instead of 4 + + // 2PI = 360°, keep in mind that ingame orientation is counter-clockwise + double rotation = 2*M_PI-atEntry->box_orientation; + double sinVal = sin(rotation); + double cosVal = cos(rotation); + + float playerBoxDistX = pl->GetPositionX() - atEntry->x; + float playerBoxDistY = pl->GetPositionY() - atEntry->y; + + float rotPlayerX = atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal; + float rotPlayerY = atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal; + + // box edges are parallel to coordiante axis, so we can treat every dimension independently :D + float dz = pl->GetPositionZ() - atEntry->z; + float dx = rotPlayerX - atEntry->x; + float dy = rotPlayerY - atEntry->y; + if( (fabs(dx) > atEntry->box_x/2 + delta) || + (fabs(dy) > atEntry->box_y/2 + delta) || (fabs(dz) > atEntry->box_z/2 + delta) ) { - sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u", - pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotateDx, rotateDy, dz, Trigger_ID); + sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u", + pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, Trigger_ID); return; } } @@ -868,6 +878,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) if(decompressedSize > 0xFFFF) { + recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case sLog.outError("UAD: Account data packet too big, size %u", decompressedSize); return; } @@ -878,10 +889,13 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) uLongf realSize = decompressedSize; if(uncompress(const_cast(dest.contents()), &realSize, const_cast(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) { + recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case sLog.outError("UAD: Failed to decompress account data"); return; } + recv_data.rpos(recv_data.wpos()); // uncompress read (recv_data.size() - recv_data.rpos()) + std::string adata; dest >> adata; @@ -987,7 +1001,8 @@ void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & recv_data ) /* WorldSession::Update( getMSTime() );*/ DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" ); - recv_data.read_skip2(); + recv_data.read_skip(); + recv_data.read_skip(); /* uint64 guid; uint32 time_skipped; @@ -1010,76 +1025,50 @@ void WorldSession::HandleFeatherFallAck(WorldPacket &/*recv_data*/) void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data) { + // no used + recv_data.rpos(recv_data.wpos()); // prevent warnings spam +/* + uint64 guid; + recv_data >> guid; + + // now can skip not our packet + if(_player->GetGUID() != guid) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK" ); - recv_data.read_skip(); // guid - recv_data.read_skip(); // unknown1 - recv_data.read_skip(); // unknown2 - recv_data.read_skip(); // PositionX - recv_data.read_skip(); // PositionY - recv_data.read_skip(); // PositionZ - recv_data.read_skip(); // Orientation - - /* - recv_data.hexlike(); + recv_data.read_skip(); // unk - recv_data >> guid; - recv_data >> unknown1; - recv_data >> unknown2; - recv_data >> PositionX; - recv_data >> PositionY; - recv_data >> PositionZ; - recv_data >> Orientation; - - // TODO for later may be we can use for anticheat - DEBUG_LOG("Guid " UI64FMTD,guid); - DEBUG_LOG("unknown1 " UI64FMTD,unknown1); - DEBUG_LOG("unknown2 %u",unknown2); - DEBUG_LOG("X %f",PositionX); - DEBUG_LOG("Y %f",PositionY); - DEBUG_LOG("Z %f",PositionZ); - DEBUG_LOG("O %f",Orientation); - */ + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); +*/ } void WorldSession::HandleMoveRootAck(WorldPacket& recv_data) { - recv_data.read_skip(); // guid - recv_data.read_skip(); // unknown1 - recv_data.read_skip(); // unknown2 - recv_data.read_skip(); // PositionX - recv_data.read_skip(); // PositionY - recv_data.read_skip(); // PositionZ - recv_data.read_skip(); // Orientation + // no used + recv_data.rpos(recv_data.wpos()); // prevent warnings spam +/* + uint64 guid; + recv_data >> guid; - /* - sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" ); - recv_data.hexlike(); - uint64 guid; - uint64 unknown1; - uint32 unknown2; - float PositionX; - float PositionY; - float PositionZ; - float Orientation; + // now can skip not our packet + if(_player->GetGUID() != guid) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } - recv_data >> guid; - recv_data >> unknown1; - recv_data >> unknown2; - recv_data >> PositionX; - recv_data >> PositionY; - recv_data >> PositionZ; - recv_data >> Orientation; + sLog.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" ); - // for later may be we can use for anticheat - DEBUG_LOG("Guid " UI64FMTD,guid); - DEBUG_LOG("unknown1 " UI64FMTD,unknown1); - DEBUG_LOG("unknown1 %u",unknown2); - DEBUG_LOG("X %f",PositionX); - DEBUG_LOG("Y %f",PositionY); - DEBUG_LOG("Z %f",PositionZ); - DEBUG_LOG("O %f",Orientation); - */ + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); +*/ } void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index bd6e92448..f946b86cf 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -218,7 +218,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if(plMover && plMover->IsBeingTeleported()) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; + } /* extract packet */ uint64 guid; @@ -231,6 +234,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ + recv_data.rpos(recv_data.wpos()); // prevent warnings spam if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) return; @@ -353,7 +357,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) // now can skip not our packet if(_player->GetGUID() != guid) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; + } // continue parse packet recv_data >> unk1; // counter or moveEvent @@ -442,6 +449,7 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) if(_player->m_mover->GetGUID() == old_mover_guid) { sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid); + recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; } @@ -460,7 +468,10 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) uint64 vehicleGUID = _player->GetCharmGUID(); if(!vehicleGUID) // something wrong here... + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam return; + } uint64 guid; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 693bac142..b1b080967 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -491,7 +491,7 @@ void ObjectMgr::LoadCreatureTemplates() CreatureInfo const* heroicInfo = GetCreatureTemplate(cInfo->HeroicEntry); if (!heroicInfo) { - sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u not exist.",cInfo->HeroicEntry,cInfo->HeroicEntry); + sLog.outErrorDb("Creature (Entry: %u) have `heroic_entry`=%u but creature entry %u not exist.", i, cInfo->HeroicEntry, cInfo->HeroicEntry); continue; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 19362bcef..1c745f496 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3859,19 +3859,34 @@ SpellCastResult Spell::CheckCast(bool strict) } } } - else if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster + else if (m_caster == target) { - // Additional check for some spells - // If 0 spell effect empty - client not send target data (need use selection) - // TODO: check it on next client version - if (m_targets.m_targetMask == TARGET_FLAG_SELF && - m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE) + + if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster { - if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection())) - m_targets.setUnitTarget(target); - else - return SPELL_FAILED_BAD_TARGETS; + // Additional check for some spells + // If 0 spell effect empty - client not send target data (need use selection) + // TODO: check it on next client version + if (m_targets.m_targetMask == TARGET_FLAG_SELF && + m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE) + { + if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection())) + m_targets.setUnitTarget(target); + else + return SPELL_FAILED_BAD_TARGETS; + } } + + // Some special spells with non-caster only mode + + // Fire Shield + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && + m_spellInfo->SpellIconID == 16) + return SPELL_FAILED_BAD_TARGETS; + + // Focus Magic (main spell) + if (m_spellInfo->Id == 54646) + return SPELL_FAILED_BAD_TARGETS; } // check pet presents @@ -4679,7 +4694,12 @@ SpellCastResult Spell::CheckPetCast(Unit* target) bool need = false; for(uint32 i = 0; i < 3; ++i) { - if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES) + if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || + m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || + m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND_2 || + m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || + m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || + m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES) { need = true; if(!target) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 09f0455f6..7ef0cc7ae 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -5438,7 +5438,7 @@ void Aura::HandleNoReagentUseAura(bool /*Apply*/, bool Real) void Aura::HandleShapeshiftBoosts(bool apply) { - uint32 spellId = 0; + uint32 spellId1 = 0; uint32 spellId2 = 0; uint32 HotWSpellId = 0; uint32 MasterShaperSpellId = 0; @@ -5448,87 +5448,92 @@ void Aura::HandleShapeshiftBoosts(bool apply) switch(form) { case FORM_CAT: - spellId = 3025; + spellId1 = 3025; HotWSpellId = 24900; MasterShaperSpellId = 48420; break; case FORM_TREE: - spellId = 5420; + spellId1 = 5420; spellId2 = 34123; MasterShaperSpellId = 48422; break; case FORM_TRAVEL: - spellId = 5419; + spellId1 = 5419; break; case FORM_AQUA: - spellId = 5421; + spellId1 = 5421; break; case FORM_BEAR: - spellId = 1178; + spellId1 = 1178; spellId2 = 21178; HotWSpellId = 24899; MasterShaperSpellId = 48418; break; case FORM_DIREBEAR: - spellId = 9635; + spellId1 = 9635; spellId2 = 21178; HotWSpellId = 24899; MasterShaperSpellId = 48418; break; case FORM_BATTLESTANCE: - spellId = 21156; + spellId1 = 21156; break; case FORM_DEFENSIVESTANCE: - spellId = 7376; + spellId1 = 7376; break; case FORM_BERSERKERSTANCE: - spellId = 7381; + spellId1 = 7381; break; case FORM_MOONKIN: - spellId = 24905; + spellId1 = 24905; // aura from effect trigger spell spellId2 = 24907; MasterShaperSpellId = 48421; break; case FORM_FLIGHT: - spellId = 33948; + spellId1 = 33948; spellId2 = 34764; break; case FORM_FLIGHT_EPIC: - spellId = 40122; + spellId1 = 40122; spellId2 = 40121; break; case FORM_METAMORPHOSIS: - spellId = 54817; + spellId1 = 54817; spellId2 = 54879; break; case FORM_SPIRITOFREDEMPTION: - spellId = 27792; + spellId1 = 27792; spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. break; + case FORM_SHADOW: + spellId1 = 49868; + + if(m_target->GetTypeId() == TYPEID_PLAYER) // Spell 49868 have same category as main form spell and share cooldown + ((Player*)m_target)->RemoveSpellCooldown(49868); + break; case FORM_GHOSTWOLF: case FORM_AMBIENT: case FORM_GHOUL: - case FORM_SHADOW: case FORM_STEALTH: case FORM_CREATURECAT: case FORM_CREATUREBEAR: - spellId = 0; + spellId1 = 0; break; } if(apply) { - if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this ); + if (spellId1) m_target->CastSpell(m_target, spellId1, true, NULL, this ); if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this); - if(m_target->GetTypeId() == TYPEID_PLAYER) + if (m_target->GetTypeId() == TYPEID_PLAYER) { const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap(); for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - if(itr->first==spellId || itr->first==spellId2) continue; + if (itr->second->state == PLAYERSPELL_REMOVED) continue; + if (itr->first==spellId1 || itr->first==spellId2) continue; SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue; @@ -5611,7 +5616,7 @@ void Aura::HandleShapeshiftBoosts(bool apply) } else { - m_target->RemoveAurasDueToSpell(spellId); + m_target->RemoveAurasDueToSpell(spellId1); m_target->RemoveAurasDueToSpell(spellId2); m_target->RemoveAurasDueToSpell(MasterShaperSpellId); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 50717b657..dabb9ae62 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4524,6 +4524,68 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return true; } +bool Unit::HandleSpellCritChanceAuraProc(Unit *pVictim, uint32 /*damage*/, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) +{ + SpellEntry const *triggeredByAuraSpell = triggeredByAura->GetSpellProto(); + + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; + + uint32 triggered_spell_id = 0; + Unit* target = pVictim; + int32 basepoints0 = 0; + + switch(triggeredByAuraSpell->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + { + switch(triggeredByAuraSpell->Id) + { + // Focus Magic + case 54646: + { + Unit* caster = triggeredByAura->GetCaster(); + if(!caster) + return false; + + triggered_spell_id = 54648; + target = caster; + break; + } + } + } + } + + // processed charge only counting case + if(!triggered_spell_id) + return true; + + SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); + + if(!triggerEntry) + { + sLog.outError("Unit::HandleHasteAuraProc: Spell %u have not existed triggered spell %u",triggeredByAuraSpell->Id,triggered_spell_id); + return false; + } + + // default case + if(!target || target!=this && !target->isAlive()) + return false; + + if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) + return false; + + if(basepoints0) + CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + else + CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura); + + if( cooldown && GetTypeId()==TYPEID_PLAYER ) + ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown); + + return true; +} + bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) { SpellEntry const *dummySpell = triggeredByAura->GetSpellProto (); @@ -5223,6 +5285,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu pVictim->CastSpell(pVictim,57669,true,castItem,triggeredByAura); return true; // no hidden cooldown } + // Divine Aegis if (dummySpell->SpellIconID == 2820) { @@ -5230,6 +5293,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 47753; break; } + // Improved Shadowform + else if (dummySpell->SpellIconID == 217) + { + if(!roll_chance_i(triggerAmount)) + return false; + + RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); + break; + } + switch(dummySpell->Id) { // Vampiric Embrace @@ -11130,6 +11204,12 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag triggeredByAura->SetInUse(false); continue; } + sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s spell crit chance aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + if (!HandleSpellCritChanceAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) + { + triggeredByAura->SetInUse(false); + continue; + } break; default: // nothing do, just charges counter diff --git a/src/game/Unit.h b/src/game/Unit.h index 6312968b0..9fc9d5160 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1551,6 +1551,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ); bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); + bool HandleSpellCritChanceAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown); bool HandleMendingAuraProc(Aura* triggeredByAura); diff --git a/src/game/VoiceChatHandler.cpp b/src/game/VoiceChatHandler.cpp index 3fc23ffcf..b799f0a18 100644 --- a/src/game/VoiceChatHandler.cpp +++ b/src/game/VoiceChatHandler.cpp @@ -26,7 +26,8 @@ void WorldSession::HandleVoiceSessionEnableOpcode( WorldPacket & recv_data ) { sLog.outDebug("WORLD: CMSG_VOICE_SESSION_ENABLE"); // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled - recv_data.read_skip2(); + recv_data.read_skip(); + recv_data.read_skip(); recv_data.hexlike(); } diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 328103f7d..3887b1bca 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -141,7 +141,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet) } /// Logging helper for unexpected opcodes -void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason) +void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char *reason) { sLog.outError( "SESSION: received unexpected opcode %s (0x%.4X) %s", LookupOpcodeName(packet->GetOpcode()), @@ -149,6 +149,15 @@ void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason) reason); } +/// Logging helper for unexpected opcodes +void WorldSession::LogUnprocessedTail(WorldPacket *packet) +{ + sLog.outError( "SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode(), + packet->rpos(),packet->wpos()); +} + /// Update the WorldSession (triggered by World update) bool WorldSession::Update(uint32 /*diff*/) { @@ -182,30 +191,40 @@ bool WorldSession::Update(uint32 /*diff*/) { // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets if(!m_playerRecentlyLogout) - logUnexpectedOpcode(packet, "the player has not logged in yet"); + LogUnexpectedOpcode(packet, "the player has not logged in yet"); } else if(_player->IsInWorld()) + { (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_TRANSFER: if(!_player) - logUnexpectedOpcode(packet, "the player has not logged in yet"); + LogUnexpectedOpcode(packet, "the player has not logged in yet"); else if(_player->IsInWorld()) - logUnexpectedOpcode(packet, "the player is still in world"); + LogUnexpectedOpcode(packet, "the player is still in world"); else + { (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } break; case STATUS_AUTHED: // prevent cheating with skip queue wait if(m_inQueue) { - logUnexpectedOpcode(packet, "the player not pass queue yet"); + LogUnexpectedOpcode(packet, "the player not pass queue yet"); break; } m_playerRecentlyLogout = false; (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); break; case STATUS_NEVER: sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", @@ -214,7 +233,7 @@ bool WorldSession::Update(uint32 /*diff*/) break; } } - catch(ByteBufferException &exception) + 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()); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 95707dd29..5be87469f 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -733,7 +733,8 @@ class MANGOS_DLL_SPEC WorldSession void moveItems(Item* myItems[], Item* hisItems[]); // logging helper - void logUnexpectedOpcode(WorldPacket *packet, const char * reason); + void LogUnexpectedOpcode(WorldPacket *packet, const char * reason); + void LogUnprocessedTail(WorldPacket *packet); Player *_player; WorldSocket *m_Socket; diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index bdd52f71d..ac6079350 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -737,7 +737,7 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct) } } } - catch(ByteBufferException &exception) + catch(ByteBufferException &) { sLog.outError("WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.", opcode, GetRemoteAddress().c_str(), m_Session?m_Session->GetAccountId():-1); diff --git a/src/shared/ByteBuffer.h b/src/shared/ByteBuffer.h index 09842781b..b40539402 100644 --- a/src/shared/ByteBuffer.h +++ b/src/shared/ByteBuffer.h @@ -27,15 +27,16 @@ class ByteBufferException { public: - ByteBufferException(bool add, size_t pos, size_t esize, size_t size):add(add), pos(pos), esize(esize), size(size) + ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size) + : add(_add), pos(_pos), esize(_esize), size(_size) { PrintPosError(); } void PrintPosError() const { - sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: %lu size: %lu) value with size: %lu",(add ? "put" : "get"),(unsigned long)pos, (unsigned long)size, (unsigned long)esize); - + sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD, + (add ? "put" : "get"), pos, size, esize); } private: bool add; @@ -262,22 +263,6 @@ class ByteBuffer template void read_skip() { read_skip(sizeof(T)); } - template - void read_skip2() { read_skip(sizeof(T1)+sizeof(T2)); } - - template<> - void read_skip() - { - uint8 size = read(); - read_skip(size); - } - - template<> - void read_skip() { read_skip(); } - - template<> - void read_skip() { read_skip(); } - void read_skip(size_t skip) { if(_rpos + skip > size()) @@ -512,7 +497,8 @@ class ByteBuffer std::vector _storage; }; -template ByteBuffer &operator<<(ByteBuffer &b, std::vector v) +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::vector v) { b << (uint32)v.size(); for (typename std::vector::iterator i = v.begin(); i != v.end(); ++i) @@ -522,7 +508,8 @@ template ByteBuffer &operator<<(ByteBuffer &b, std::vector v) return b; } -template ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) { uint32 vsize; b >> vsize; @@ -536,7 +523,8 @@ template ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) return b; } -template ByteBuffer &operator<<(ByteBuffer &b, std::list v) +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::list v) { b << (uint32)v.size(); for (typename std::list::iterator i = v.begin(); i != v.end(); ++i) @@ -546,7 +534,8 @@ template ByteBuffer &operator<<(ByteBuffer &b, std::list v) return b; } -template ByteBuffer &operator>>(ByteBuffer &b, std::list &v) +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::list &v) { uint32 vsize; b >> vsize; @@ -560,7 +549,8 @@ template ByteBuffer &operator>>(ByteBuffer &b, std::list &v) return b; } -template ByteBuffer &operator<<(ByteBuffer &b, std::map &m) +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::map &m) { b << (uint32)m.size(); for (typename std::map::iterator i = m.begin(); i != m.end(); ++i) @@ -570,7 +560,8 @@ template ByteBuffer &operator<<(ByteBuffer &b, std::map return b; } -template ByteBuffer &operator>>(ByteBuffer &b, std::map &m) +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::map &m) { uint32 msize; b >> msize; @@ -584,4 +575,23 @@ template ByteBuffer &operator>>(ByteBuffer &b, std::map } return b; } + +template<> +inline void ByteBuffer::read_skip() +{ + std::string temp; + *this >> temp; +} + +template<> +inline void ByteBuffer::read_skip() +{ + read_skip(); +} + +template<> +inline void ByteBuffer::read_skip() +{ + read_skip(); +} #endif diff --git a/src/shared/Log.cpp b/src/shared/Log.cpp index 97c2e7164..a4166dcee 100644 --- a/src/shared/Log.cpp +++ b/src/shared/Log.cpp @@ -369,7 +369,11 @@ void Log::outString( const char * str, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stdout,str,); + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); if(m_colored) ResetColor(true); @@ -379,7 +383,6 @@ void Log::outString( const char * str, ... ) { outTimestamp(logfile); - va_list ap; va_start(ap, str); vfprintf(logfile, str, ap); fprintf(logfile, "\n" ); @@ -401,7 +404,11 @@ void Log::outError( const char * err, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stderr,err,); + va_list ap; + + va_start(ap, err); + vutf8printf(stderr, err, &ap); + va_end(ap); if(m_colored) ResetColor(false); @@ -412,7 +419,6 @@ void Log::outError( const char * err, ... ) outTimestamp(logfile); fprintf(logfile, "ERROR:" ); - va_list ap; va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); @@ -434,7 +440,11 @@ void Log::outErrorDb( const char * err, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stderr,err,); + va_list ap; + + va_start(ap, err); + vutf8printf(stderr, err, &ap); + va_end(ap); if(m_colored) ResetColor(false); @@ -446,7 +456,6 @@ void Log::outErrorDb( const char * err, ... ) outTimestamp(logfile); fprintf(logfile, "ERROR:" ); - va_list ap; va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); @@ -483,7 +492,10 @@ void Log::outBasic( const char * str, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stdout,str,); + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); if(m_colored) ResetColor(true); @@ -518,7 +530,10 @@ void Log::outDetail( const char * str, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stdout,str,); + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); if(m_colored) ResetColor(true); @@ -527,12 +542,14 @@ void Log::outDetail( const char * str, ... ) } if(logfile && m_logFileLevel > 1) { - va_list ap; outTimestamp(logfile); + + va_list ap; va_start(ap, str); vfprintf(logfile, str, ap); - fprintf(logfile, "\n" ); va_end(ap); + + fprintf(logfile, "\n" ); fflush(logfile); } @@ -548,7 +565,10 @@ void Log::outDebugInLine( const char * str, ... ) if(m_colored) SetColor(true,m_colors[LogDebug]); - UTF8PRINTF(stdout,str,); + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); if(m_colored) ResetColor(true); @@ -574,7 +594,10 @@ void Log::outDebug( const char * str, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stdout,str,); + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); if(m_colored) ResetColor(true); @@ -609,7 +632,10 @@ void Log::outCommand( uint32 account, const char * str, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stdout,str,); + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); if(m_colored) ResetColor(true); @@ -691,7 +717,11 @@ void Log::outMenu( const char * str, ... ) if(m_includeTime) outTime(); - UTF8PRINTF(stdout,str,); + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); ResetColor(true); @@ -699,7 +729,6 @@ void Log::outMenu( const char * str, ... ) { outTimestamp(logfile); - va_list ap; va_start(ap, str); vfprintf(logfile, str, ap); va_end(ap); diff --git a/src/shared/Util.cpp b/src/shared/Util.cpp index 0b70aac87..b5cd93fd0 100644 --- a/src/shared/Util.cpp +++ b/src/shared/Util.cpp @@ -135,12 +135,8 @@ uint32 TimeStringToSecs(const std::string& timestring) { if(isdigit(*itr)) { - std::string str; //very complicated typecast char->const char*; is there no better way? - str += *itr; - const char* tmp = str.c_str(); - buffer*=10; - buffer+=atoi(tmp); + buffer+= (*itr)-'0'; } else { @@ -419,3 +415,29 @@ bool Utf8FitTo(const std::string& str, std::wstring search) return true; } + +void utf8printf(FILE *out, const char *str, ...) +{ + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); +} + +void vutf8printf(FILE *out, const char *str, va_list* ap) +{ +#if PLATFORM == PLATFORM_WINDOWS + char temp_buf[32*1024]; + wchar_t wtemp_buf[32*1024]; + + size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); + + size_t wtemp_len = 32*1024-1; + Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); + + CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); + fprintf(out, temp_buf); +#else + vfprintf(out, str, *ap); +#endif +} diff --git a/src/shared/Util.h b/src/shared/Util.h index 121bbc292..522c917d9 100644 --- a/src/shared/Util.h +++ b/src/shared/Util.h @@ -283,32 +283,8 @@ std::wstring GetMainPartOfName(std::wstring wname, uint32 declension); bool utf8ToConsole(const std::string& utf8str, std::string& conStr); bool consoleToUtf8(const std::string& conStr,std::string& utf8str); bool Utf8FitTo(const std::string& str, std::wstring search); - -#if PLATFORM == PLATFORM_WINDOWS -#define UTF8PRINTF(OUT,FRM,RESERR) \ -{ \ - char temp_buf[32*1024]; \ - va_list ap; \ - va_start(ap, FRM); \ - size_t temp_len = vsnprintf(temp_buf,32*1024,FRM,ap); \ - va_end(ap); \ - \ - wchar_t wtemp_buf[32*1024]; \ - size_t wtemp_len = 32*1024-1; \ - if(!Utf8toWStr(temp_buf,temp_len,wtemp_buf,wtemp_len)) \ - return RESERR; \ - CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);\ - fprintf(OUT,temp_buf); \ -} -#else -#define UTF8PRINTF(OUT,FRM,RESERR) \ -{ \ - va_list ap; \ - va_start(ap, FRM); \ - vfprintf(OUT, FRM, ap ); \ - va_end(ap); \ -} -#endif +void utf8printf(FILE *out, const char *str, ...); +void vutf8printf(FILE *out, const char *str, va_list* ap); bool IsIPAddress(char const* ipaddress); uint32 CreatePIDFile(const std::string& filename); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1f3737b85..448c53470 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8383" + #define REVISION_NR "8396" #endif // __REVISION_NR_H__