aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/Maps/MapTree.cpp3
-rw-r--r--src/server/game/Chat/Channels/Channel.h2
-rw-r--r--src/server/game/Entities/Item/Item.cpp2
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp23
-rw-r--r--src/server/game/Entities/Player/Player.h7
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp2
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp2
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h19
-rw-r--r--src/server/game/Server/WorldSession.cpp252
-rw-r--r--src/server/game/Server/WorldSession.h14
-rw-r--r--src/server/game/Spells/SpellInfo.cpp13
-rw-r--r--src/server/game/Weather/Weather.cpp2
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp2
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp9
-rw-r--r--src/server/shared/Packets/ByteBuffer.h5
16 files changed, 327 insertions, 32 deletions
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp
index bb57079c389..d592d795125 100644
--- a/src/server/collision/Maps/MapTree.cpp
+++ b/src/server/collision/Maps/MapTree.cpp
@@ -157,8 +157,7 @@ namespace VMAP
{
float maxDist = (pos2 - pos1).magnitude();
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
- if (maxDist == std::numeric_limits<float>::max() ||
- maxDist == std::numeric_limits<float>::infinity())
+ if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist))
return false;
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 9ad6877d929..115e340762e 100644
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -25,7 +25,7 @@
#include "Common.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
#include "WorldPacket.h"
class Player;
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index ee389ed7311..4573b85c7f3 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -27,7 +27,7 @@
#include "ScriptMgr.h"
#include "ConditionMgr.h"
#include "Player.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
void AddItemsSetItem(Player* player, Item* item)
{
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index eb4e2fcf2ee..768f5907c19 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -30,7 +30,7 @@
#include "Unit.h"
#include "Util.h"
#include "Group.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
#define PET_XP_FACTOR 0.05f
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 71e37b1a256..f30c98957a7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7480,6 +7480,19 @@ void Player::UpdateArea(uint32 newArea)
}
else
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
+
+ uint32 const areaRestFlag = (GetTeam() == ALLIANCE) ? AREA_FLAG_REST_ZONE_ALLIANCE : AREA_FLAG_REST_ZONE_HORDE;
+ if (area && area->flags & areaRestFlag)
+ {
+ SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
+ SetRestType(REST_TYPE_IN_FACTION_AREA);
+ InnEnter(time(0), GetMapId(), 0, 0, 0);
+ }
+ else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_FACTION_AREA)
+ {
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
+ SetRestType(REST_TYPE_NO);
+ }
}
void Player::UpdateZone(uint32 newZone, uint32 newArea)
@@ -7565,8 +7578,9 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
SetRestType(REST_TYPE_NO);
}
}
- else // Recently left a capital city
+ else if (GetRestType() != REST_TYPE_IN_FACTION_AREA) // handled in UpdateArea
{
+ // Recently left a capital city
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO);
}
@@ -8201,7 +8215,12 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType att
{
HandleStatModifier(unitMod, unitModType, float(aura->GetAmount()), apply);
if (unitModType == TOTAL_VALUE)
- ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, aura->GetAmount(), apply);
+ {
+ if (aura->GetAmount() > 0)
+ ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, aura->GetAmount(), apply);
+ else
+ ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, aura->GetAmount(), apply);
+ }
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7e1d9be0f88..48a2209cc14 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -729,9 +729,10 @@ class InstanceSave;
enum RestType
{
- REST_TYPE_NO = 0,
- REST_TYPE_IN_TAVERN = 1,
- REST_TYPE_IN_CITY = 2
+ REST_TYPE_NO = 0,
+ REST_TYPE_IN_TAVERN = 1,
+ REST_TYPE_IN_CITY = 2,
+ REST_TYPE_IN_FACTION_AREA = 3 // used with AREA_FLAG_REST_ZONE_*
};
enum TeleportToOptions
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index 8c8e470f80b..25315a30da1 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -19,7 +19,7 @@
#include "SocialMgr.h"
#include "DatabaseEnv.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
#include "WorldPacket.h"
#include "Player.h"
#include "ObjectMgr.h"
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index 69e677bd89d..46b73e74068 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -24,7 +24,7 @@
#include "World.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index e581d7d1544..7b07abdf962 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -25,12 +25,6 @@
#include "Common.h"
-// Note: this include need for be sure have full definition of class WorldSession
-// if this class definition not complete then VS for x64 release use different size for
-// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from
-// table opcodeTable in source when Opcode.h included but WorldSession.h not included
-#include "WorldSession.h"
-
/// List of Opcodes
enum Opcodes
{
@@ -1366,8 +1360,15 @@ enum PacketProcessing
PROCESS_THREADSAFE //packet is thread-safe - process it in Map::Update()
};
+class WorldSession;
class WorldPacket;
+#if defined(__GNUC__)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
struct OpcodeHandler
{
char const* name;
@@ -1378,6 +1379,12 @@ struct OpcodeHandler
extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
+#if defined(__GNUC__)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
/// Lookup opcode name for human understandable logging
inline const char* LookupOpcodeName(uint16 id)
{
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 89242bada6e..81d33d30a35 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -277,12 +277,13 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
//! loop caused by re-enqueueing the same packets over and over again, we stop updating this session
//! and continue updating others. The re-enqueued packets will be handled in the next Update call for this session.
uint32 processedPackets = 0;
+ time_t currentTime = time(NULL);
while (m_Socket && !m_Socket->IsClosed() &&
!_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket &&
_recvQueue.next(packet, updater))
{
- if (!AntiDOS.EvaluateOpcode(*packet))
+ if (!AntiDOS.EvaluateOpcode(*packet, currentTime))
{
KickPlayer();
}
@@ -1236,14 +1237,38 @@ void WorldSession::InvalidateRBACData()
_RBACData = NULL;
}
-bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p) const
+bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const
{
- if (IsOpcodeAllowed(p.GetOpcode()))
- return true;
+ PacketCounter& packetCounter = _PacketThrottlingMap[p.GetOpcode()];
+ if (packetCounter.lastReceiveTime != time)
+ {
+ packetCounter.lastReceiveTime = time;
+ packetCounter.amountCounter = 0;
+ }
- // Opcode not allowed, let the punishment begin
- TC_LOG_INFO("network", "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)",
- Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+ uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode());
+
+ bool dosTriggered = false;
+ // Check if player is flooding some packets
+ if (++packetCounter.amountCounter > maxPacketCounterAllowed)
+ {
+ dosTriggered = true;
+ TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, flooding packet (opc: %u, size: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+ }
+
+ // Then check if player is sending packets not allowed
+ if (!IsOpcodeAllowed(p.GetOpcode()))
+ {
+ dosTriggered = true;
+ // Opcode not allowed, let the punishment begin
+ TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+ }
+
+ // Return true if everything is fine, otherwise apply the configured policy
+ if (!dosTriggered)
+ return true;
switch (_policy)
{
@@ -1272,3 +1297,216 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p) const
return true;
}
}
+
+
+uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) const
+{
+ uint32 maxPacketCounterAllowed;
+ switch (opcode)
+ {
+ case CMSG_ITEM_QUERY_SINGLE:
+ case CMSG_ITEM_NAME_QUERY:
+ case CMSG_GUILD_QUERY:
+ case CMSG_NAME_QUERY:
+ case CMSG_PET_NAME_QUERY:
+ case CMSG_GAMEOBJECT_QUERY:
+ case CMSG_CREATURE_QUERY:
+ case CMSG_NPC_TEXT_QUERY:
+ case CMSG_ARENA_TEAM_QUERY:
+ case CMSG_TAXINODE_STATUS_QUERY:
+ case CMSG_TAXIQUERYAVAILABLENODES:
+ case CMSG_QUESTGIVER_QUERY_QUEST:
+ case CMSG_QUEST_QUERY:
+ case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY:
+ case CMSG_QUERY_QUESTS_COMPLETED:
+ case CMSG_QUEST_POI_QUERY:
+ case CMSG_QUERY_TIME:
+ case CMSG_PAGE_TEXT_QUERY:
+ case CMSG_PETITION_QUERY:
+ case CMSG_QUERY_INSPECT_ACHIEVEMENTS:
+ case CMSG_AREA_SPIRIT_HEALER_QUERY:
+ case CMSG_CORPSE_MAP_POSITION_QUERY:
+ case CMSG_MOVE_TIME_SKIPPED:
+ case CMSG_GUILD_BANK_QUERY_TAB:
+ case MSG_GUILD_BANK_LOG_QUERY:
+ case MSG_QUERY_GUILD_BANK_TEXT:
+ case MSG_CORPSE_QUERY:
+ case MSG_QUERY_NEXT_MAIL_TIME:
+ case MSG_GUILD_EVENT_LOG_QUERY:
+ case MSG_MOVE_SET_FACING:
+ {
+ maxPacketCounterAllowed = 200;
+ break;
+ }
+
+ case CMSG_MESSAGECHAT:
+ {
+ maxPacketCounterAllowed = 50;
+ break;
+ }
+
+ case CMSG_CONTACT_LIST:
+ {
+ maxPacketCounterAllowed = 10;
+ break;
+ }
+
+ case CMSG_WHO:
+ case CMSG_GAMEOBJ_USE:
+ case CMSG_GAMEOBJ_REPORT_USE:
+ case CMSG_SPELLCLICK:
+ case CMSG_PLAYER_LOGOUT:
+ case CMSG_LOGOUT_REQUEST:
+ case CMSG_LOGOUT_CANCEL:
+ case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
+ case CMSG_REQUEST_VEHICLE_PREV_SEAT:
+ case CMSG_REQUEST_VEHICLE_NEXT_SEAT:
+ case CMSG_REQUEST_VEHICLE_SWITCH_SEAT:
+ case CMSG_TOGGLE_PVP:
+ case CMSG_ADD_FRIEND:
+ case CMSG_DEL_FRIEND:
+ case CMSG_SET_CONTACT_NOTES:
+ case CMSG_RESET_INSTANCES:
+ case CMSG_HEARTH_AND_RESURRECT:
+ case CMSG_CHAR_CREATE:
+ case CMSG_READY_FOR_ACCOUNT_DATA_TIMES:
+ case CMSG_CHAR_ENUM:
+ case CMSG_REALM_SPLIT:
+ case CMSG_CHAR_DELETE:
+ case CMSG_PLAYER_LOGIN:
+ case CMSG_PET_ABANDON:
+ case CMSG_PET_RENAME:
+ case CMSG_CHAR_RENAME:
+ case CMSG_CHAR_CUSTOMIZE:
+ case CMSG_CHAR_RACE_CHANGE:
+ case CMSG_CHAR_FACTION_CHANGE:
+ case CMSG_GMTICKET_CREATE:
+ case CMSG_GMTICKET_UPDATETEXT:
+ case CMSG_GMTICKET_DELETETICKET:
+ case CMSG_GMSURVEY_SUBMIT:
+ case CMSG_GM_REPORT_LAG:
+ case CMSG_BUG:
+ case CMSG_GMRESPONSE_RESOLVE:
+ case CMSG_ACTIVATETAXIEXPRESS:
+ case CMSG_ACTIVATETAXI:
+ case CMSG_SELF_RES:
+ case CMSG_INITIATE_TRADE:
+ case CMSG_BEGIN_TRADE:
+ case CMSG_UNLEARN_SKILL:
+ case CMSG_DISMISS_CONTROLLED_VEHICLE:
+ case CMSG_REQUEST_VEHICLE_EXIT:
+ case CMSG_LEARN_PREVIEW_TALENTS:
+ case CMSG_LEARN_PREVIEW_TALENTS_PET:
+ case CMSG_PLAYER_VEHICLE_ENTER:
+ case CMSG_CONTROLLER_EJECT_PASSENGER:
+ case CMSG_EQUIPMENT_SET_SAVE:
+ case CMSG_DELETEEQUIPMENT_SET:
+ case CMSG_REMOVE_GLYPH:
+ case CMSG_ALTER_APPEARANCE:
+ case CMSG_QUESTGIVER_ACCEPT_QUEST:
+ case CMSG_QUESTGIVER_CHOOSE_REWARD:
+ case CMSG_QUESTGIVER_REQUEST_REWARD:
+ case CMSG_QUESTGIVER_CANCEL:
+ case CMSG_QUESTLOG_REMOVE_QUEST:
+ case CMSG_QUEST_CONFIRM_ACCEPT:
+ case CMSG_QUESTGIVER_COMPLETE_QUEST:
+ case CMSG_DISMISS_CRITTER:
+ case CMSG_REPOP_REQUEST:
+ case CMSG_PETITION_BUY:
+ case CMSG_PETITION_SIGN:
+ case CMSG_TURN_IN_PETITION:
+ case CMSG_COMPLETE_CINEMATIC:
+ case CMSG_ITEM_REFUND:
+ case CMSG_SOCKET_GEMS:
+ case CMSG_WRAP_ITEM:
+ case CMSG_BUY_BANK_SLOT:
+ case CMSG_GROUP_ACCEPT:
+ case CMSG_GROUP_DECLINE:
+ case CMSG_GROUP_UNINVITE_GUID:
+ case CMSG_GROUP_UNINVITE:
+ case CMSG_GROUP_SET_LEADER:
+ case CMSG_GROUP_DISBAND:
+ case CMSG_GROUP_RAID_CONVERT:
+ case CMSG_GROUP_CHANGE_SUB_GROUP:
+ case CMSG_GROUP_ASSISTANT_LEADER:
+ case CMSG_REQUEST_PARTY_MEMBER_STATS:
+ case CMSG_OPT_OUT_OF_LOOT:
+ case CMSG_BATTLEMASTER_JOIN_ARENA:
+ case CMSG_LEAVE_BATTLEFIELD:
+ case CMSG_REPORT_PVP_AFK:
+ case CMSG_DUEL_ACCEPTED:
+ case CMSG_DUEL_CANCELLED:
+ case CMSG_SETSHEATHED:
+ case CMSG_CALENDAR_GET_CALENDAR:
+ case CMSG_CALENDAR_ADD_EVENT:
+ case CMSG_CALENDAR_UPDATE_EVENT:
+ case CMSG_CALENDAR_REMOVE_EVENT:
+ case CMSG_CALENDAR_COPY_EVENT:
+ case CMSG_CALENDAR_EVENT_INVITE:
+ case CMSG_CALENDAR_EVENT_SIGNUP:
+ case CMSG_CALENDAR_EVENT_RSVP:
+ case CMSG_CALENDAR_EVENT_REMOVE_INVITE:
+ case CMSG_CALENDAR_EVENT_MODERATOR_STATUS:
+ case CMSG_CALENDAR_COMPLAIN:
+ case CMSG_ARENA_TEAM_INVITE:
+ case CMSG_ARENA_TEAM_ACCEPT:
+ case CMSG_ARENA_TEAM_DECLINE:
+ case CMSG_ARENA_TEAM_LEAVE:
+ case CMSG_ARENA_TEAM_DISBAND:
+ case CMSG_ARENA_TEAM_REMOVE:
+ case CMSG_ARENA_TEAM_LEADER:
+ case CMSG_LOOT_METHOD:
+ case CMSG_GUILD_INVITE:
+ case CMSG_GUILD_ACCEPT:
+ case CMSG_GUILD_DECLINE:
+ case CMSG_GUILD_LEAVE:
+ case CMSG_GUILD_DISBAND:
+ case CMSG_GUILD_LEADER:
+ case CMSG_GUILD_MOTD:
+ case CMSG_GUILD_SET_PUBLIC_NOTE:
+ case CMSG_GUILD_SET_OFFICER_NOTE:
+ case CMSG_GUILD_RANK:
+ case CMSG_GUILD_ADD_RANK:
+ case CMSG_GUILD_DEL_RANK:
+ case CMSG_GUILD_INFO_TEXT:
+ case CMSG_GUILD_BANK_DEPOSIT_MONEY:
+ case CMSG_GUILD_BANK_WITHDRAW_MONEY:
+ case CMSG_GUILD_BANK_BUY_TAB:
+ case CMSG_GUILD_BANK_UPDATE_TAB:
+ case CMSG_SET_GUILD_BANK_TEXT:
+ case MSG_SAVE_GUILD_EMBLEM:
+ case MSG_PETITION_RENAME:
+ case MSG_PETITION_DECLINE:
+ case MSG_TALENT_WIPE_CONFIRM:
+ case MSG_SET_DUNGEON_DIFFICULTY:
+ case MSG_SET_RAID_DIFFICULTY:
+ case MSG_RANDOM_ROLL:
+ case MSG_RAID_TARGET_UPDATE:
+ case MSG_PARTY_ASSIGNMENT:
+ case MSG_RAID_READY_CHECK:
+ {
+ maxPacketCounterAllowed = 3;
+ break;
+ }
+
+ case CMSG_SET_ACTION_BUTTON:
+ {
+ maxPacketCounterAllowed = MAX_ACTION_BUTTONS;
+ break;
+ }
+
+ case CMSG_ITEM_REFUND_INFO:
+ {
+ maxPacketCounterAllowed = PLAYER_SLOTS_COUNT;
+ break;
+ }
+
+ default:
+ {
+ maxPacketCounterAllowed = 100;
+ break;
+ }
+ }
+
+ return maxPacketCounterAllowed;
+}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 9d1a05ae753..7bea0ef9a85 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -28,6 +28,7 @@
#include "AddonMgr.h"
#include "DatabaseEnv.h"
#include "World.h"
+#include "Opcodes.h"
#include "WorldPacket.h"
#include "Cryptography/BigNumber.h"
#include "AccountMgr.h"
@@ -196,6 +197,12 @@ class CharacterCreateInfo
uint8 CharCount;
};
+struct PacketCounter
+{
+ time_t lastReceiveTime;
+ uint32 amountCounter;
+};
+
/// Player session in the World
class WorldSession
{
@@ -929,7 +936,7 @@ class WorldSession
friend class World;
public:
DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) { }
- bool EvaluateOpcode(WorldPacket& p) const;
+ bool EvaluateOpcode(WorldPacket& p, time_t time) const;
void AllowOpcode(uint16 opcode, bool allow) { _isOpcodeAllowed[opcode] = allow; }
protected:
enum Policy
@@ -948,12 +955,17 @@ class WorldSession
return itr->second;
}
+ uint32 GetMaxPacketCounterAllowed(uint16 opcode) const;
+
WorldSession* Session;
private:
typedef std::unordered_map<uint16, bool> OpcodeStatusMap;
OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes
Policy _policy;
+ typedef std::unordered_map<uint16, PacketCounter> PacketThrottlingMap;
+ // mark this member as "mutable" so it can be modified even in const functions
+ mutable PacketThrottlingMap _PacketThrottlingMap;
DosProtection(DosProtection const& right) = delete;
DosProtection& operator=(DosProtection const& right) = delete;
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 21c36510a32..ba4c3deca85 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -24,6 +24,7 @@
#include "Player.h"
#include "Battleground.h"
#include "Vehicle.h"
+#include "Pet.h"
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
{
@@ -1505,8 +1506,16 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
// creature/player specific target checks
if (unitTarget)
{
- if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT && unitTarget->IsInCombat())
- return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+ if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT)
+ {
+ if (unitTarget->IsInCombat())
+ return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+ // player with active pet counts as a player in combat
+ else if (Player const* player = unitTarget->ToPlayer())
+ if (Pet* pet = player->GetPet())
+ if (pet->GetVictim() && !pet->HasUnitState(UNIT_STATE_CONTROLLED))
+ return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
+ }
// only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
if (((AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) != 0) != unitTarget->HasAuraType(SPELL_AURA_GHOST))
diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp
index cb332df9a41..8d39f553910 100644
--- a/src/server/game/Weather/Weather.cpp
+++ b/src/server/game/Weather/Weather.cpp
@@ -28,7 +28,7 @@
#include "ObjectMgr.h"
#include "Util.h"
#include "ScriptMgr.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
/// Create the Weather object
Weather::Weather(uint32 zone, WeatherData const* weatherChances)
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index 59dc591ccd0..5cf5cde75fd 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -27,7 +27,7 @@
#include "AutoPtr.h"
#include "Player.h"
#include "WorldPacket.h"
-#include "Opcodes.h"
+#include "WorldSession.h"
namespace WeatherMgr
{
diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp
index 2739a8453df..725312eafce 100644
--- a/src/server/scripts/Spells/spell_hunter.cpp
+++ b/src/server/scripts/Spells/spell_hunter.cpp
@@ -744,8 +744,13 @@ class spell_hun_sniper_training : public SpellScriptLoader
{
Unit* target = GetTarget();
uint32 spellId = SPELL_HUNTER_SNIPER_TRAINING_BUFF_R1 + GetId() - SPELL_HUNTER_SNIPER_TRAINING_R1;
- if (!target->HasAura(spellId))
- target->CastSpell(target, spellId, true, 0, aurEff);
+ target->CastSpell(target, spellId, true, 0, aurEff);
+ if (Player* playerTarget = GetUnitOwner()->ToPlayer())
+ {
+ int32 baseAmount = aurEff->GetBaseAmount();
+ int32 amount = playerTarget->CalculateSpellDamage(playerTarget, GetSpellInfo(), aurEff->GetEffIndex(), &baseAmount);
+ GetEffect(EFFECT_0)->SetAmount(amount);
+ }
}
}
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index dd0a9d5fdf4..9f766a72d19 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -31,6 +31,7 @@
#include <vector>
#include <cstring>
#include <time.h>
+#include <math.h>
// Root of ByteBuffer exception hierarchy
class ByteBufferException : public std::exception
@@ -241,12 +242,16 @@ class ByteBuffer
ByteBuffer &operator>>(float &value)
{
value = read<float>();
+ if (!std::isfinite(value))
+ throw ByteBufferException();
return *this;
}
ByteBuffer &operator>>(double &value)
{
value = read<double>();
+ if (!std::isfinite(value))
+ throw ByteBufferException();
return *this;
}