Last active
December 26, 2022 11:44
-
-
Save Ovahlord/c9a26aa5b4d1292effaa15383ad07e0b to your computer and use it in GitHub Desktop.
Spell and Loot batching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/server/game/Entities/Player/ActionBatchObject.cpp b/src/server/game/Entities/Player/ActionBatchObject.cpp | |
new file mode 100644 | |
index 0000000000..dfefef657a | |
--- /dev/null | |
+++ b/src/server/game/Entities/Player/ActionBatchObject.cpp | |
@@ -0,0 +1,126 @@ | |
+/* | |
+* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> | |
+* | |
+* This program is free software; you can redistribute it and/or modify it | |
+* under the terms of the GNU General Public License as published by the | |
+* Free Software Foundation; either version 2 of the License, or (at your | |
+* option) any later version. | |
+* | |
+* This program is distributed in the hope that it will be useful, but WITHOUT | |
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
+* more details. | |
+* | |
+* You should have received a copy of the GNU General Public License along | |
+* with this program. If not, see <http://www.gnu.org/licenses/>. | |
+*/ | |
+ | |
+#include "ActionBatchObject.h" | |
+#include "SpellInfo.h" | |
+#include "SpellMgr.h" | |
+#include "WorldSession.h" | |
+ | |
+ActionBatchObject::ActionBatchObject(Player* owner) : m_owner(owner) | |
+{ | |
+} | |
+ | |
+void ActionBatchObject::CreateBatchObject(WorldPacket& data) | |
+{ | |
+ if (IsPacketBatchable(data)) // checking for some special cases (eg. self casts) | |
+ m_packetBatch.push(data); | |
+} | |
+ | |
+void ActionBatchObject::ProcessBatchedObjects() | |
+{ | |
+ while (!m_packetBatch.empty()) | |
+ { | |
+ WorldPacket data = m_packetBatch.front(); | |
+ | |
+ WorldSession* session = m_owner->GetSession(); | |
+ | |
+ switch (data.GetOpcode()) | |
+ { | |
+ case CMSG_CAST_SPELL: | |
+ session->HandleCastSpellOpcode(data); | |
+ break; | |
+ case CMSG_CANCEL_CAST: | |
+ session->HandleCancelCastOpcode(data); | |
+ break; | |
+ case CMSG_CANCEL_AURA: | |
+ session->HandleCancelAuraOpcode(data); | |
+ break; | |
+ case CMSG_CANCEL_AUTO_REPEAT_SPELL: | |
+ session->HandleCancelAutoRepeatSpellOpcode(data); | |
+ break; | |
+ case CMSG_CANCEL_CHANNELLING: | |
+ session->HandleCancelChanneling(data); | |
+ break; | |
+ case CMSG_CANCEL_GROWTH_AURA: | |
+ session->HandleCancelGrowthAuraOpcode(data); | |
+ break; | |
+ case CMSG_CANCEL_MOUNT_AURA: | |
+ session->HandleCancelMountAuraOpcode(data); | |
+ break; | |
+ case CMSG_LOOT: | |
+ session->HandleLootOpcode(data); | |
+ break; | |
+ case CMSG_LOOT_CURRENCY: | |
+ session->HandleLootCurrencyOpcode(data); | |
+ break; | |
+ case CMSG_LOOT_MASTER_GIVE: | |
+ session->HandleLootMasterGiveOpcode(data); | |
+ break; | |
+ case CMSG_LOOT_METHOD: | |
+ session->HandleLootMethodOpcode(data); | |
+ break; | |
+ case CMSG_LOOT_MONEY: | |
+ session->HandleLootMoneyOpcode(data); | |
+ break; | |
+ case CMSG_LOOT_RELEASE: | |
+ session->HandleLootReleaseOpcode(data); | |
+ break; | |
+ case CMSG_LOOT_ROLL: | |
+ session->HandleLootRoll(data); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ m_packetBatch.pop(); | |
+ } | |
+} | |
+ | |
+bool ActionBatchObject::IsPacketBatchable(WorldPacket& data) const | |
+{ | |
+ switch (data.GetOpcode()) | |
+ { | |
+ case CMSG_CAST_SPELL: | |
+ { | |
+ if (m_owner->m_unitMovedByMe != m_owner) // vehicle casts and mind controls are also getting batched | |
+ return true; | |
+ | |
+ // only reading the spell targets for now | |
+ data.read_skip<uint8>(); // cast count | |
+ data.read_skip<uint32>(); // spell Id | |
+ data.read_skip<uint32>(); // glyph index | |
+ data.read_skip<uint8>(); // cast flags | |
+ SpellCastTargets targets; | |
+ targets.Read(data, m_owner); | |
+ data.rfinish(); | |
+ | |
+ // if we target ourself the cast will be instant. Otherwise it will be batched | |
+ if (targets.GetUnitTarget() && targets.GetUnitTarget() == m_owner) | |
+ { | |
+ if (WorldSession* session = m_owner->GetSession()) | |
+ session->HandleCastSpellOpcode(data); | |
+ | |
+ return false; | |
+ } | |
+ | |
+ return true; | |
+ } | |
+ default: | |
+ return true; | |
+ } | |
+ | |
+ return true; | |
+} | |
diff --git a/src/server/game/Entities/Player/ActionBatchObject.h b/src/server/game/Entities/Player/ActionBatchObject.h | |
new file mode 100644 | |
index 0000000000..2fb7b57bd6 | |
--- /dev/null | |
+++ b/src/server/game/Entities/Player/ActionBatchObject.h | |
@@ -0,0 +1,43 @@ | |
+/* | |
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> | |
+ * | |
+ * This program is free software; you can redistribute it and/or modify it | |
+ * under the terms of the GNU General Public License as published by the | |
+ * Free Software Foundation; either version 2 of the License, or (at your | |
+ * option) any later version. | |
+ * | |
+ * This program is distributed in the hope that it will be useful, but WITHOUT | |
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
+ * more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License along | |
+ * with this program. If not, see <http://www.gnu.org/licenses/>. | |
+ */ | |
+ | |
+#ifndef ActionBatchObject_h__ | |
+#define ActionBatchObject_h__ | |
+ | |
+#include "Define.h" | |
+#include "Spell.h" | |
+#include "WorldPacket.h" | |
+ | |
+class TC_GAME_API ActionBatchObject | |
+{ | |
+ public: | |
+ ActionBatchObject(Player* owner); | |
+ | |
+ void CreateBatchObject(WorldPacket& data); | |
+ void ProcessBatchedObjects(); | |
+ | |
+ bool IsPacketBatchable(WorldPacket& data) const; | |
+ | |
+ private: | |
+ // Packet storage which contains all stored up packets | |
+ std::queue<WorldPacket> m_packetBatch; | |
+ | |
+ // Player owner who is going to process all batched up packets | |
+ Player* m_owner; | |
+}; | |
+ | |
+#endif // ActionBatchObject_h__ | |
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp | |
index df7d7e481f..1a8406c819 100644 | |
--- a/src/server/game/Entities/Player/Player.cpp | |
+++ b/src/server/game/Entities/Player/Player.cpp | |
@@ -19,6 +19,7 @@ | |
#include "Player.h" | |
#include "AccountMgr.h" | |
#include "AchievementMgr.h" | |
+#include "ActionBatchObject.h" | |
#include "Archaeology.h" | |
#include "ArenaTeam.h" | |
#include "ArenaTeamMgr.h" | |
@@ -413,6 +414,7 @@ Player::Player(WorldSession* session): Unit(true) | |
m_reputationMgr = new ReputationMgr(this); | |
_hasValidLFGLeavePoint = false; | |
_archaeology = new Archaeology(this); | |
+ m_actionBatchObjects = new ActionBatchObject(this); | |
} | |
Player::~Player() | |
@@ -447,6 +449,7 @@ Player::~Player() | |
delete m_reputationMgr; | |
delete _cinematicMgr; | |
delete _archaeology; | |
+ delete m_actionBatchObjects; | |
for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) | |
delete _voidStorageItems[i]; | |
@@ -1388,6 +1391,12 @@ void Player::Update(uint32 p_time) | |
if (IsHasDelayedTeleport() && IsAlive()) | |
TeleportTo(m_teleport_dest, m_teleport_options); | |
+ m_batchProcessingTimer.Update(p_time); | |
+ if (m_batchProcessingTimer.Passed()) | |
+ { | |
+ m_actionBatchObjects->ProcessBatchedObjects(); | |
+ m_batchProcessingTimer.Reset(400); // confirmed by blueposts | |
+ } | |
} | |
void Player::setDeathState(DeathState s) | |
@@ -28412,3 +28421,8 @@ void Player::SendTamePetFailure(PetTameFailureReason reason) | |
data << uint8(reason); | |
SendDirectMessage(&data); | |
} | |
+ | |
+void Player::AddBatchAction(WorldPacket& packet) | |
+{ | |
+ m_actionBatchObjects->CreateBatchObject(packet); | |
+} | |
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h | |
index da89290b97..f1d5ec6dfc 100644 | |
--- a/src/server/game/Entities/Player/Player.h | |
+++ b/src/server/game/Entities/Player/Player.h | |
@@ -56,7 +56,7 @@ struct VendorItem; | |
template<class T> | |
class AchievementMgr; | |
- | |
+class ActionBatchObject; | |
class Archaeology; | |
class Bag; | |
class Battleground; | |
@@ -2373,6 +2373,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> | |
void DeleteFromPlayerPetDataStore(uint32 petNumber); | |
void AddToPlayerPetDataStore(PlayerPetData* playerPetData); | |
+ // Action Batching | |
+ void AddBatchAction(WorldPacket& packet); | |
+ | |
protected: | |
// Gamemaster whisper whitelist | |
GuidList WhisperList; | |
@@ -2751,6 +2754,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> | |
Archaeology* _archaeology; | |
std::vector<PlayerPetData*> PlayerPetDataStore; | |
+ | |
+ // Action batching system | |
+ TimeTrackerSmall m_batchProcessingTimer; | |
+ ActionBatchObject* m_actionBatchObjects; | |
}; | |
TC_GAME_API void AddItemsSetItem(Player* player, Item* item); | |
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp | |
index c9097271e9..de629d7625 100644 | |
--- a/src/server/game/Handlers/MiscHandler.cpp | |
+++ b/src/server/game/Handlers/MiscHandler.cpp | |
@@ -2061,3 +2061,8 @@ void WorldSession::HandleRequestResearchHistory(WorldPacket & /*recv_data*/) | |
if (Player* player = GetPlayer()) | |
player->NotifyRequestResearchHistory(); | |
} | |
+ | |
+void WorldSession::HandleBatchedAction(WorldPacket& recv_data) | |
+{ | |
+ _player->AddBatchAction(recv_data); | |
+} | |
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp | |
index 9df9b15eeb..7399d9fa4a 100644 | |
--- a/src/server/game/Server/Protocol/Opcodes.cpp | |
+++ b/src/server/game/Server/Protocol/Opcodes.cpp | |
@@ -147,16 +147,16 @@ void OpcodeTable::Initialize() | |
DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_GUILD_FILTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter ); | |
DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_REMOVE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent ); | |
DEFINE_OPCODE_HANDLER(CMSG_CALENDAR_UPDATE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarUpdateEvent ); | |
- DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCancelAuraOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AUTO_REPEAT_SPELL, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCancelAutoRepeatSpellOpcode); | |
- DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CHANNELLING, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCancelChanneling ); | |
- DEFINE_OPCODE_HANDLER(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCancelMountAuraOpcode ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_AUTO_REPEAT_SPELL, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_CHANNELLING, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleBatchedAction ); | |
DEFINE_OPCODE_HANDLER(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); | |
DEFINE_OPCODE_HANDLER(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCancelTempEnchantmentOpcode); | |
DEFINE_OPCODE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode); | |
- DEFINE_OPCODE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleBatchedAction ); | |
DEFINE_OPCODE_HANDLER(CMSG_CHANGEPLAYER_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleChangePlayerDifficulty ); | |
DEFINE_OPCODE_HANDLER(CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleChangeSeatsOnControlledVehicle); | |
DEFINE_OPCODE_HANDLER(CMSG_CHANNEL_ANNOUNCEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements ); | |
@@ -337,13 +337,13 @@ void OpcodeTable::Initialize() | |
DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode ); | |
DEFINE_OPCODE_HANDLER(CMSG_LOGOUT_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode ); | |
DEFINE_OPCODE_HANDLER(CMSG_LOG_DISCONNECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT_CURRENCY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootCurrencyOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT_MASTER_GIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT_METHOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMoneyOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT_RELEASE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootReleaseOpcode ); | |
- DEFINE_OPCODE_HANDLER(CMSG_LOOT_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_CURRENCY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_MASTER_GIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_METHOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_RELEASE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
+ DEFINE_OPCODE_HANDLER(CMSG_LOOT_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBatchedAction ); | |
DEFINE_OPCODE_HANDLER(CMSG_MAIL_CREATE_TEXT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem ); | |
DEFINE_OPCODE_HANDLER(CMSG_MAIL_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete ); | |
DEFINE_OPCODE_HANDLER(CMSG_MAIL_MARK_AS_READ, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMailMarkAsRead ); | |
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h | |
index 1f775bc56d..262e137a40 100644 | |
--- a/src/server/game/Server/WorldSession.h | |
+++ b/src/server/game/Server/WorldSession.h | |
@@ -1067,6 +1067,7 @@ class TC_GAME_API WorldSession | |
void HandleViolenceLevel(WorldPacket& recvPacket); | |
void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket); | |
void HandleRequestCategoryCooldowns(WorldPacket& recvPacket); | |
+ void HandleBatchedAction(WorldPacket& recvPacket); | |
void SendStreamingMovie(); | |
void HandleRequestResearchHistory(WorldPacket& recv_data); | |
int32 HandleEnableNagleAlgorithm(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment