feat(Core/Scripts): Optimize PlayerScripts by calling only overridden/implemented functions. (#18672)

* feat(Core/Scripts): Optimize PlayerScripts by calling only overridden/implemented functions.

* Fix codestyle.

* Fix typo

* PLAYERHOOK_END is not a hook

* Address code review feedback.

Co-authored-by: Winfidonarleyan <dowlandtop@yandex.com>

* Codestyle fixes

* Fix typo



Co-authored-by: PkllonG

---------

Co-authored-by: Winfidonarleyan <dowlandtop@yandex.com>
This commit is contained in:
Anton Popovichenko
2024-04-11 22:08:30 +02:00
committed by GitHub
parent fd029f81aa
commit f792b0d708
11 changed files with 452 additions and 1054 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -24,10 +24,186 @@
#include "AchievementMgr.h"
#include "KillRewarder.h"
enum PlayerHook {
PLAYERHOOK_ON_PLAYER_JUST_DIED,
PLAYERHOOK_ON_PLAYER_RELEASED_GHOST,
PLAYERHOOK_ON_SEND_INITIAL_PACKETS_BEFORE_ADD_TO_MAP,
PLAYERHOOK_ON_BATTLEGROUND_DESERTION,
PLAYERHOOK_ON_PLAYER_COMPLETE_QUEST,
PLAYERHOOK_ON_PVP_KILL,
PLAYERHOOK_ON_PLAYER_PVP_FLAG_CHANGE,
PLAYERHOOK_ON_CREATURE_KILL,
PLAYERHOOK_ON_CREATURE_KILLED_BY_PET,
PLAYERHOOK_ON_PLAYER_KILLED_BY_CREATURE,
PLAYERHOOK_ON_LEVEL_CHANGED,
PLAYERHOOK_ON_FREE_TALENT_POINTS_CHANGED,
PLAYERHOOK_ON_TALENTS_RESET,
PLAYERHOOK_ON_AFTER_SPEC_SLOT_CHANGED,
PLAYERHOOK_ON_BEFORE_UPDATE,
PLAYERHOOK_ON_UPDATE,
PLAYERHOOK_ON_MONEY_CHANGED,
PLAYERHOOK_ON_BEFORE_LOOT_MONEY,
PLAYERHOOK_ON_GIVE_EXP,
PLAYERHOOK_ON_REPUTATION_CHANGE,
PLAYERHOOK_ON_REPUTATION_RANK_CHANGE,
PLAYERHOOK_ON_LEARN_SPELL,
PLAYERHOOK_ON_FORGOT_SPELL,
PLAYERHOOK_ON_DUEL_REQUEST,
PLAYERHOOK_ON_DUEL_START,
PLAYERHOOK_ON_DUEL_END,
PLAYERHOOK_ON_CHAT,
PLAYERHOOK_ON_BEFORE_SEND_CHAT_MESSAGE,
PLAYERHOOK_ON_CHAT_WITH_RECEIVER,
PLAYERHOOK_ON_CHAT_WITH_GROUP,
PLAYERHOOK_ON_CHAT_WITH_GUILD,
PLAYERHOOK_ON_CHAT_WITH_CHANNEL,
PLAYERHOOK_ON_EMOTE,
PLAYERHOOK_ON_TEXT_EMOTE,
PLAYERHOOK_ON_SPELL_CAST,
PLAYERHOOK_ON_LOAD_FROM_DB,
PLAYERHOOK_ON_LOGIN,
PLAYERHOOK_ON_BEFORE_LOGOUT,
PLAYERHOOK_ON_LOGOUT,
PLAYERHOOK_ON_CREATE,
PLAYERHOOK_ON_DELETE,
PLAYERHOOK_ON_FAILED_DELETE,
PLAYERHOOK_ON_SAVE,
PLAYERHOOK_ON_BIND_TO_INSTANCE,
PLAYERHOOK_ON_UPDATE_ZONE,
PLAYERHOOK_ON_UPDATE_AREA,
PLAYERHOOK_ON_MAP_CHANGED,
PLAYERHOOK_ON_BEFORE_TELEPORT,
PLAYERHOOK_ON_UPDATE_FACTION,
PLAYERHOOK_ON_ADD_TO_BATTLEGROUND,
PLAYERHOOK_ON_QUEUE_RANDOM_DUNGEON,
PLAYERHOOK_ON_REMOVE_FROM_BATTLEGROUND,
PLAYERHOOK_ON_ACHI_COMPLETE,
PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE,
PLAYERHOOK_ON_CRITERIA_PROGRESS,
PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS,
PLAYERHOOK_ON_ACHI_SAVE,
PLAYERHOOK_ON_CRITERIA_SAVE,
PLAYERHOOK_ON_GOSSIP_SELECT,
PLAYERHOOK_ON_GOSSIP_SELECT_CODE,
PLAYERHOOK_ON_BEING_CHARMED,
PLAYERHOOK_ON_AFTER_SET_VISIBLE_ITEM_SLOT,
PLAYERHOOK_ON_AFTER_MOVE_ITEM_FROM_INVENTORY,
PLAYERHOOK_ON_EQUIP,
PLAYERHOOK_ON_PLAYER_JOIN_BG,
PLAYERHOOK_ON_PLAYER_JOIN_ARENA,
PLAYERHOOK_GET_CUSTOM_GET_ARENA_TEAM_ID,
PLAYERHOOK_GET_CUSTOM_ARENA_PERSONAL_RATING,
PLAYERHOOK_ON_GET_MAX_PERSONAL_ARENA_RATING_REQUIREMENT,
PLAYERHOOK_ON_LOOT_ITEM,
PLAYERHOOK_ON_BEFORE_FILL_QUEST_LOOT_ITEM,
PLAYERHOOK_ON_STORE_NEW_ITEM,
PLAYERHOOK_ON_CREATE_ITEM,
PLAYERHOOK_ON_QUEST_REWARD_ITEM,
PLAYERHOOK_CAN_PLACE_AUCTION_BID,
PLAYERHOOK_ON_GROUP_ROLL_REWARD_ITEM,
PLAYERHOOK_ON_BEFORE_OPEN_ITEM,
PLAYERHOOK_ON_BEFORE_QUEST_COMPLETE,
PLAYERHOOK_ON_QUEST_COMPUTE_EXP,
PLAYERHOOK_ON_BEFORE_DURABILITY_REPAIR,
PLAYERHOOK_ON_BEFORE_BUY_ITEM_FROM_VENDOR,
PLAYERHOOK_ON_BEFORE_STORE_OR_EQUIP_NEW_ITEM,
PLAYERHOOK_ON_AFTER_STORE_OR_EQUIP_NEW_ITEM,
PLAYERHOOK_ON_AFTER_UPDATE_MAX_POWER,
PLAYERHOOK_ON_AFTER_UPDATE_MAX_HEALTH,
PLAYERHOOK_ON_BEFORE_UPDATE_ATTACK_POWER_AND_DAMAGE,
PLAYERHOOK_ON_AFTER_UPDATE_ATTACK_POWER_AND_DAMAGE,
PLAYERHOOK_ON_BEFORE_INIT_TALENT_FOR_LEVEL,
PLAYERHOOK_ON_FIRST_LOGIN,
PLAYERHOOK_ON_SET_MAX_LEVEL,
PLAYERHOOK_CAN_JOIN_IN_BATTLEGROUND_QUEUE,
PLAYERHOOK_SHOULD_BE_REWARDED_WITH_MONEY_INSTEAD_OF_EXP,
PLAYERHOOK_ON_BEFORE_TEMP_SUMMON_INIT_STATS,
PLAYERHOOK_ON_BEFORE_GUARDIAN_INIT_STATS_FOR_LEVEL,
PLAYERHOOK_ON_AFTER_GUARDIAN_INIT_STATS_FOR_LEVEL,
PLAYERHOOK_ON_BEFORE_LOAD_PET_FROM_DB,
PLAYERHOOK_CAN_JOIN_IN_ARENA_QUEUE,
PLAYERHOOK_CAN_BATTLEFIELD_PORT,
PLAYERHOOK_CAN_GROUP_INVITE,
PLAYERHOOK_CAN_GROUP_ACCEPT,
PLAYERHOOK_CAN_SELL_ITEM,
PLAYERHOOK_CAN_SEND_MAIL,
PLAYERHOOK_PETITION_BUY,
PLAYERHOOK_PETITION_SHOW_LIST,
PLAYERHOOK_ON_REWARD_KILL_REWARDER,
PLAYERHOOK_CAN_GIVE_MAIL_REWARD_AT_GIVE_LEVEL,
PLAYERHOOK_ON_DELETE_FROM_DB,
PLAYERHOOK_CAN_REPOP_AT_GRAVEYARD,
PLAYERHOOK_ON_PLAYER_IS_CLASS,
PLAYERHOOK_ON_GET_MAX_SKILL_VALUE,
PLAYERHOOK_ON_PLAYER_HAS_ACTIVE_POWER_TYPE,
PLAYERHOOK_ON_UPDATE_GATHERING_SKILL,
PLAYERHOOK_ON_UPDATE_CRAFTING_SKILL,
PLAYERHOOK_ON_UPDATE_FISHING_SKILL,
PLAYERHOOK_CAN_AREA_EXPLORE_AND_OUTDOOR,
PLAYERHOOK_ON_VICTIM_REWARD_BEFORE,
PLAYERHOOK_ON_VICTIM_REWARD_AFTER,
PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE_BEFORE,
PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE,
PLAYERHOOK_CAN_ARMOR_DAMAGE_MODIFIER,
PLAYERHOOK_ON_GET_FERAL_AP_BONUS,
PLAYERHOOK_CAN_APPLY_WEAPON_DEPENDENT_AURA_DAMAGE_MOD,
PLAYERHOOK_CAN_APPLY_EQUIP_SPELL,
PLAYERHOOK_CAN_APPLY_EQUIP_SPELLS_ITEM_SET,
PLAYERHOOK_CAN_CAST_ITEM_COMBAT_SPELL,
PLAYERHOOK_CAN_CAST_ITEM_USE_SPELL,
PLAYERHOOK_ON_APPLY_AMMO_BONUSES,
PLAYERHOOK_CAN_EQUIP_ITEM,
PLAYERHOOK_CAN_UNEQUIP_ITEM,
PLAYERHOOK_CAN_USE_ITEM,
PLAYERHOOK_CAN_SAVE_EQUIP_NEW_ITEM,
PLAYERHOOK_CAN_APPLY_ENCHANTMENT,
PLAYERHOOK_PASSED_QUEST_KILLED_MONSTER_CREDIT,
PLAYERHOOK_CHECK_ITEM_IN_SLOT_AT_LOAD_INVENTORY,
PLAYERHOOK_NOT_AVOID_SATISFY,
PLAYERHOOK_NOT_VISIBLE_GLOBALLY_FOR,
PLAYERHOOK_ON_GET_ARENA_PERSONAL_RATING,
PLAYERHOOK_ON_GET_ARENA_TEAM_ID,
PLAYERHOOK_ON_IS_FFA_PVP,
PLAYERHOOK_ON_FFA_PVP_STATE_UPDATE,
PLAYERHOOK_ON_IS_PVP,
PLAYERHOOK_ON_GET_MAX_SKILL_VALUE_FOR_LEVEL,
PLAYERHOOK_NOT_SET_ARENA_TEAM_INFO_FIELD,
PLAYERHOOK_CAN_JOIN_LFG,
PLAYERHOOK_CAN_ENTER_MAP,
PLAYERHOOK_CAN_INIT_TRADE,
PLAYERHOOK_CAN_SET_TRADE_ITEM,
PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY,
PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY_DETECT,
PLAYERHOOK_ON_PLAYER_RESURRECT,
PLAYERHOOK_ON_BEFORE_CHOOSE_GRAVEYARD,
PLAYERHOOK_CAN_PLAYER_USE_CHAT,
PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT,
PLAYERHOOK_CAN_PLAYER_USE_GROUP_CHAT,
PLAYERHOOK_CAN_PLAYER_USE_GUILD_CHAT,
PLAYERHOOK_CAN_PLAYER_USE_CHANNEL_CHAT,
PLAYERHOOK_ON_PLAYER_LEARN_TALENTS,
PLAYERHOOK_ON_PLAYER_ENTER_COMBAT,
PLAYERHOOK_ON_PLAYER_LEAVE_COMBAT,
PLAYERHOOK_ON_QUEST_ABANDON,
PLAYERHOOK_ON_GET_QUEST_RATE,
PLAYERHOOK_ON_CAN_PLAYER_FLY_IN_ZONE,
PLAYERHOOK_ANTICHEAT_SET_CAN_FLY_BY_SERVER,
PLAYERHOOK_ANTICHEAT_SET_UNDER_ACK_MOUNT,
PLAYERHOOK_ANTICHEAT_SET_ROOT_ACK_UPD,
PLAYERHOOK_ANTICHEAT_SET_JUMPING_BY_OPCODE,
PLAYERHOOK_ANTICHEAT_UPDATE_MOVEMENT_INFO,
PLAYERHOOK_ANTICHEAT_HANDLE_DOUBLE_JUMP,
PLAYERHOOK_ANTICHEAT_CHECK_MOVEMENT_INFO,
PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED,
PLAYERHOOK_ON_AFTER_CREATURE_LOOT,
PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY,
PLAYERHOOK_END
};
class PlayerScript : public ScriptObject
{
protected:
PlayerScript(const char* name);
PlayerScript(const char* name, std::vector<uint16> enabledHooks = std::vector<uint16>());
public:
// Called when a player dies

View File

@@ -710,30 +710,42 @@ public:
typedef std::map<uint32, TScript*> ScriptMap;
typedef typename ScriptMap::iterator ScriptMapIterator;
typedef std::vector<TScript*> ScriptVector;
typedef std::vector<std::pair<TScript*,std::vector<uint16>>> ScriptVector;
typedef typename ScriptVector::iterator ScriptVectorIterator;
typedef std::vector<std::vector<TScript*>> EnabledHooksVector;
typedef typename EnabledHooksVector::iterator EnabledHooksVectorIterator;
// The actual list of scripts. This will be accessed concurrently, so it must not be modified
// after server startup.
static ScriptMap ScriptPointerList;
// After database load scripts
static ScriptVector ALScripts;
// The list of hook types with the list of enabled scripts for this specific hook.
// With this approach, we wouldn't call all available hooks in case if we override just one hook.
static EnabledHooksVector EnabledHooks;
static void AddScript(TScript* const script)
static void AddScript(TScript* const script, std::vector<uint16> enabledHooks = {})
{
ASSERT(script);
if (!_checkMemory(script))
return;
if (EnabledHooks.empty())
EnabledHooks.resize(script->GetTotalAvailableHooks());
if (script->isAfterLoadScript())
{
ALScripts.push_back(script);
ALScripts.emplace_back(script, std::move(enabledHooks));
}
else
{
script->checkValidity();
for (uint16 v : enabledHooks)
EnabledHooks[v].emplace_back(script);
// We're dealing with a code-only script; just add it.
ScriptPointerList[_scriptIdCounter++] = script;
sScriptMgr->IncreaseScriptCount();
@@ -742,9 +754,9 @@ public:
static void AddALScripts()
{
for(ScriptVectorIterator it = ALScripts.begin(); it != ALScripts.end(); ++it)
for (ScriptVectorIterator it = ALScripts.begin(); it != ALScripts.end(); ++it)
{
TScript* const script = *it;
TScript* const script = (*it).first;
script->checkValidity();
@@ -776,6 +788,14 @@ public:
// If the script is already assigned -> delete it!
if (oldScript)
{
for (auto& vIt : EnabledHooks)
for (size_t i = 0; i < vIt.size(); ++i)
if (vIt[i] == oldScript)
{
vIt.erase(vIt.begin() + i);
break;
}
delete oldScript;
}
@@ -798,6 +818,9 @@ public:
}
else
{
for (uint16 v : (*it).second)
EnabledHooks[v].emplace_back(script);
// We're dealing with a code-only script; just add it.
ScriptPointerList[_scriptIdCounter++] = script;
sScriptMgr->IncreaseScriptCount();
@@ -842,7 +865,8 @@ private:
// Instantiate static members of ScriptRegistry.
template<class TScript> std::map<uint32, TScript*> ScriptRegistry<TScript>::ScriptPointerList;
template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::ALScripts;
template<class TScript> std::vector<std::pair<TScript*,std::vector<uint16>>> ScriptRegistry<TScript>::ALScripts;
template<class TScript> std::vector<std::vector<TScript*>> ScriptRegistry<TScript>::EnabledHooks;
template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0;
#endif

View File

@@ -69,4 +69,14 @@ inline bool ReturnValidBool(Optional<bool> ret, bool need = false)
return ret && *ret ? need : !need;
}
#define CALL_ENABLED_HOOKS(scriptType, hookType, action) \
if (!ScriptRegistry<scriptType>::EnabledHooks[hookType].empty()) \
for (auto const& script : ScriptRegistry<scriptType>::EnabledHooks[hookType]) { action; }
#define CALL_ENABLED_BOOLEAN_HOOKS(scriptType, hookType, action) \
if (ScriptRegistry<scriptType>::EnabledHooks[hookType].empty()) \
return true; \
for (auto const& script : ScriptRegistry<scriptType>::EnabledHooks[hookType]) { if (action) return false; } \
return true;
#endif // _SCRIPT_MGR_MACRO_H_

View File

@@ -53,8 +53,10 @@ public:
[[nodiscard]] const std::string& GetName() const { return _name; }
[[nodiscard]] uint16 GetTotalAvailableHooks() { return _totalAvailableHooks; }
protected:
ScriptObject(const char* name) : _name(std::string(name))
ScriptObject(const char* name, uint16 totalAvailableHooks = 0) : _name(std::string(name)), _totalAvailableHooks(totalAvailableHooks)
{
}
@@ -62,6 +64,7 @@ protected:
private:
const std::string _name;
const uint16 _totalAvailableHooks;
};
template<class TObject>