diff --git a/conf/mod_ale.conf.dist b/conf/mod_ale.conf.dist index 3eca4cc50d..db4c8cbc40 100644 --- a/conf/mod_ale.conf.dist +++ b/conf/mod_ale.conf.dist @@ -8,6 +8,12 @@ # Default: true - (enabled) # false - (disabled) # +# ALE.CompatibilityMode +# Description: Toggles ALE between compatibility mode (single-threaded) or multistate mode. +# Compatibility mode limits the engine to a single global Lua state. +# Default: true - (enabled) +# false - (disabled) +# # ALE.TraceBack # Description: Sets whether to use debug.traceback function on a lua error or not. # Notice that you can redefine the function. @@ -19,6 +25,12 @@ # The path can be relative or absolute. # Default: "lua_scripts" # +# ALE.OnlyOnMaps +# Description: When ALE is enabled, a state will only be created for a list of specified maps. +# This only works in multistate mode. +# Default: "" - (enabled on all maps) +# "0,1,2,..." - (enabled on specific maps only) +# # ALE.PlayerAnnounceReload # Description: Enable or disable whether the reload announcement is sent to players (Lowest security level). # Default: false - (disabled) @@ -61,8 +73,10 @@ # false - (disabled) ALE.Enabled = true +ALE.CompatibilityMode = true ALE.TraceBack = false ALE.ScriptPath = "lua_scripts" +ALE.OnlyOnMaps = "" ALE.PlayerAnnounceReload = false ALE.RequirePaths = "" ALE.RequireCPaths = "" diff --git a/src/ALE_SC.cpp b/src/ALE_SC.cpp index 60fe1013c3..b4c6f9e595 100644 --- a/src/ALE_SC.cpp +++ b/src/ALE_SC.cpp @@ -21,6 +21,7 @@ #include "LuaEngine.h" #include "Pet.h" #include "Player.h" +#include "Vehicle.h" #include "ScriptMgr.h" #include "ScriptedGossip.h" @@ -32,7 +33,7 @@ class ALE_AllCreatureScript : public AllCreatureScript // Creature bool CanCreatureGossipHello(Player* player, Creature* creature) override { - if (sALE->OnGossipHello(player, creature)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnGossipHello(player, creature)) return true; return false; @@ -40,7 +41,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override { - if (sALE->OnGossipSelect(player, creature, sender, action)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnGossipSelect(player, creature, sender, action)) return true; return false; @@ -48,7 +49,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code) override { - if (sALE->OnGossipSelectCode(player, creature, sender, action, code)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnGossipSelectCode(player, creature, sender, action, code)) return true; return false; @@ -56,6 +57,7 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureAddWorld(Creature* creature) override { + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId()); sALE->OnAddToWorld(creature); sALE->OnAllCreatureAddToWorld(creature); @@ -65,12 +67,14 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureRemoveWorld(Creature* creature) override { + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId()); sALE->OnRemoveFromWorld(creature); sALE->OnAllCreatureRemoveFromWorld(creature); } bool CanCreatureQuestAccept(Player* player, Creature* creature, Quest const* quest) override { + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId()); sALE->OnPlayerQuestAccept(player, quest); sALE->OnQuestAccept(player, creature, quest); return false; @@ -78,7 +82,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt) override { - if (sALE->OnQuestReward(player, creature, quest, opt)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnQuestReward(player, creature, quest, opt)) { ClearGossipMenuFor(player); return true; @@ -89,7 +93,7 @@ class ALE_AllCreatureScript : public AllCreatureScript CreatureAI* GetCreatureAI(Creature* creature) const override { - if (CreatureAI* luaAI = sALE->GetAI(creature)) + if (CreatureAI* luaAI = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->GetAI(creature)) return luaAI; return nullptr; @@ -97,12 +101,12 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature) override { - sALE->OnAllCreatureSelectLevel(cinfo, creature); + ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnAllCreatureSelectLevel(cinfo, creature); } void OnBeforeCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature, uint8& level) override { - sALE->OnAllCreatureBeforeSelectLevel(cinfo, creature, level); + ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnAllCreatureBeforeSelectLevel(cinfo, creature, level); } }; @@ -113,21 +117,22 @@ class ALE_AllGameObjectScript : public AllGameObjectScript void OnGameObjectAddWorld(GameObject* go) override { - sALE->OnAddToWorld(go); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnAddToWorld(go); } void OnGameObjectRemoveWorld(GameObject* go) override { - sALE->OnRemoveFromWorld(go); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnRemoveFromWorld(go); } void OnGameObjectUpdate(GameObject* go, uint32 diff) override { - sALE->UpdateAI(go, diff); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->UpdateAI(go, diff); } bool CanGameObjectGossipHello(Player* player, GameObject* go) override { + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId()); if (sALE->OnGossipHello(player, go)) return true; @@ -139,26 +144,27 @@ class ALE_AllGameObjectScript : public AllGameObjectScript void OnGameObjectDamaged(GameObject* go, Player* player) override { - sALE->OnDamaged(go, player); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnDamaged(go, player); } void OnGameObjectDestroyed(GameObject* go, Player* player) override { - sALE->OnDestroyed(go, player); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnDestroyed(go, player); } void OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* /*unit*/) override { - sALE->OnLootStateChanged(go, state); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnLootStateChanged(go, state); } void OnGameObjectStateChanged(GameObject* go, uint32 state) override { - sALE->OnGameObjectStateChanged(go, state); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnGameObjectStateChanged(go, state); } bool CanGameObjectQuestAccept(Player* player, GameObject* go, Quest const* quest) override { + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId()); sALE->OnPlayerQuestAccept(player, quest); sALE->OnQuestAccept(player, go, quest); return false; @@ -166,7 +172,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action) override { - if (sALE->OnGossipSelect(player, go, sender, action)) + if (ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnGossipSelect(player, go, sender, action)) return true; return false; @@ -174,7 +180,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code) override { - if (sALE->OnGossipSelectCode(player, go, sender, action, code)) + if (ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnGossipSelectCode(player, go, sender, action, code)) return true; return false; @@ -182,6 +188,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt) override { + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId()); if (sALE->OnQuestAccept(player, go, quest)) { sALE->OnPlayerQuestAccept(player, quest); @@ -196,7 +203,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript GameObjectAI* GetGameObjectAI(GameObject* go) const override { - sALE->OnSpawn(go); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnSpawn(go); return nullptr; } }; @@ -208,6 +215,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemQuestAccept(Player* player, Item* item, Quest const* quest) override { + ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId()); if (sALE->OnQuestAccept(player, item, quest)) { sALE->OnPlayerQuestAccept(player, quest); @@ -219,7 +227,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemUse(Player* player, Item* item, SpellCastTargets const& targets) override { - if (!sALE->OnUse(player, item, targets)) + if (!ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnUse(player, item, targets)) return true; return false; @@ -227,7 +235,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemExpire(Player* player, ItemTemplate const* proto) override { - if (sALE->OnExpire(player, proto)) + if (ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnExpire(player, proto)) return false; return true; @@ -235,7 +243,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemRemove(Player* player, Item* item) override { - if (sALE->OnRemove(player, item)) + if (ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnRemove(player, item)) return false; return true; @@ -243,12 +251,12 @@ class ALE_AllItemScript : public AllItemScript void OnItemGossipSelect(Player* player, Item* item, uint32 sender, uint32 action) override { - sALE->HandleGossipSelectOption(player, item, sender, action, ""); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, item, sender, action, ""); } void OnItemGossipSelectCode(Player* player, Item* item, uint32 sender, uint32 action, const char* code) override { - sALE->HandleGossipSelectOption(player, item, sender, action, code); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, item, sender, action, code); } }; @@ -267,38 +275,50 @@ class ALE_AllMapScript : public AllMapScript void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript** instanceData, bool /*load*/, std::string /*data*/, uint32 /*completedEncounterMask*/) override { + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) + { + if (!ALE::GetMapState(instanceMap->GetId(), instanceMap->GetInstanceId())) + ALE::CreateMapState(instanceMap->GetId(), instanceMap->GetInstanceId()); + } if (instanceData) - *instanceData = sALE->GetInstanceData(instanceMap); + *instanceData = ALE::GetMapStateOrGlobal(instanceMap->GetId(), instanceMap->GetInstanceId())->GetInstanceData(instanceMap); } void OnDestroyInstance(MapInstanced* /*mapInstanced*/, Map* map) override { - sALE->FreeInstanceId(map->GetInstanceId()); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->FreeInstanceId(map->GetInstanceId()); } void OnCreateMap(Map* map) override { - sALE->OnCreate(map); + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) + { + if (!ALE::GetMapState(map->GetId(), map->GetInstanceId())) + ALE::CreateMapState(map->GetId(), map->GetInstanceId()); + } + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnCreate(map); } void OnDestroyMap(Map* map) override { - sALE->OnDestroy(map); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnDestroy(map); + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) + ALE::DestroyMapState(map->GetId(), map->GetInstanceId()); } void OnPlayerEnterAll(Map* map, Player* player) override { - sALE->OnPlayerEnter(map, player); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnPlayerEnter(map, player); } void OnPlayerLeaveAll(Map* map, Player* player) override { - sALE->OnPlayerLeave(map, player); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnPlayerLeave(map, player); } void OnMapUpdate(Map* map, uint32 diff) override { - sALE->OnUpdate(map, diff); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnUpdate(map, diff); } }; @@ -314,22 +334,22 @@ class ALE_AuctionHouseScript : public AuctionHouseScript void OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnAdd(ah, entry); + gALE->OnAdd(ah, entry); } void OnAuctionRemove(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnRemove(ah, entry); + gALE->OnRemove(ah, entry); } void OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnSuccessful(ah, entry); + gALE->OnSuccessful(ah, entry); } void OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnExpire(ah, entry); + gALE->OnExpire(ah, entry); } }; @@ -345,22 +365,22 @@ class ALE_BGScript : public BGScript void OnBattlegroundStart(Battleground* bg) override { - sALE->OnBGStart(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGStart(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } void OnBattlegroundEnd(Battleground* bg, TeamId winnerTeam) override { - sALE->OnBGEnd(bg, bg->GetBgTypeID(), bg->GetInstanceID(), winnerTeam); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGEnd(bg, bg->GetBgTypeID(), bg->GetInstanceID(), winnerTeam); } void OnBattlegroundDestroy(Battleground* bg) override { - sALE->OnBGDestroy(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGDestroy(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } void OnBattlegroundCreate(Battleground* bg) override { - sALE->OnBGCreate(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGCreate(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } }; @@ -373,7 +393,7 @@ class ALE_CommandSC : public CommandSC bool OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr) override { - if (!sALE->OnCommand(handler, std::string(cmdStr).c_str())) + if (!gALE->OnCommand(handler, std::string(cmdStr).c_str())) { return false; } @@ -390,13 +410,13 @@ class ALE_ALEScript : public ALEScript // Weather void OnWeatherChange(Weather* weather, WeatherState state, float grade) override { - sALE->OnChange(weather, weather->GetZone(), state, grade); + gALE->OnChange(weather, weather->GetZone(), state, grade); } // AreaTriger bool CanAreaTrigger(Player* player, AreaTrigger const* trigger) override { - if (sALE->OnAreaTrigger(player, trigger)) + if (ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnAreaTrigger(player, trigger)) return true; return false; @@ -413,12 +433,12 @@ class ALE_GameEventScript : public GameEventScript void OnStart(uint16 eventID) override { - sALE->OnGameEventStart(eventID); + gALE->OnGameEventStart(eventID); } void OnStop(uint16 eventID) override { - sALE->OnGameEventStop(eventID); + gALE->OnGameEventStop(eventID); } }; @@ -436,32 +456,32 @@ class ALE_GroupScript : public GroupScript void OnAddMember(Group* group, ObjectGuid guid) override { - sALE->OnAddMember(group, guid); + gALE->OnAddMember(group, guid); } void OnInviteMember(Group* group, ObjectGuid guid) override { - sALE->OnInviteMember(group, guid); + gALE->OnInviteMember(group, guid); } void OnRemoveMember(Group* group, ObjectGuid guid, RemoveMethod method, ObjectGuid /* kicker */, const char* /* reason */) override { - sALE->OnRemoveMember(group, guid, method); + gALE->OnRemoveMember(group, guid, method); } void OnChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid) override { - sALE->OnChangeLeader(group, newLeaderGuid, oldLeaderGuid); + gALE->OnChangeLeader(group, newLeaderGuid, oldLeaderGuid); } void OnDisband(Group* group) override { - sALE->OnDisband(group); + gALE->OnDisband(group); } void OnCreate(Group* group, Player* leader) override { - sALE->OnCreate(group, leader->GetGUID(), group->GetGroupType()); + gALE->OnCreate(group, leader->GetGUID(), group->GetGroupType()); } }; @@ -484,58 +504,58 @@ class ALE_GuildScript : public GuildScript void OnAddMember(Guild* guild, Player* player, uint8& plRank) override { - sALE->OnAddMember(guild, player, plRank); + gALE->OnAddMember(guild, player, plRank); } void OnRemoveMember(Guild* guild, Player* player, bool isDisbanding, bool /*isKicked*/) override { - sALE->OnRemoveMember(guild, player, isDisbanding); + gALE->OnRemoveMember(guild, player, isDisbanding); } void OnMOTDChanged(Guild* guild, const std::string& newMotd) override { - sALE->OnMOTDChanged(guild, newMotd); + gALE->OnMOTDChanged(guild, newMotd); } void OnInfoChanged(Guild* guild, const std::string& newInfo) override { - sALE->OnInfoChanged(guild, newInfo); + gALE->OnInfoChanged(guild, newInfo); } void OnCreate(Guild* guild, Player* leader, const std::string& name) override { - sALE->OnCreate(guild, leader, name); + gALE->OnCreate(guild, leader, name); } void OnDisband(Guild* guild) override { - sALE->OnDisband(guild); + gALE->OnDisband(guild); } void OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, bool isRepair) override { - sALE->OnMemberWitdrawMoney(guild, player, amount, isRepair); + gALE->OnMemberWitdrawMoney(guild, player, amount, isRepair); } void OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount) override { - sALE->OnMemberDepositMoney(guild, player, amount); + gALE->OnMemberDepositMoney(guild, player, amount); } void OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId, bool isDestBank, uint8 destContainer, uint8 destSlotId) override { - sALE->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId); + gALE->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId); } void OnEvent(Guild* guild, uint8 eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) override { - sALE->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank); + gALE->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank); } void OnBankEvent(Guild* guild, uint8 eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) override { - sALE->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId); + gALE->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId); } }; @@ -548,7 +568,7 @@ class ALE_LootScript : public LootScript void OnLootMoney(Player* player, uint32 gold) override { - sALE->OnLootMoney(player, gold); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLootMoney(player, gold); } }; @@ -561,6 +581,7 @@ class ALE_MiscScript : public MiscScript void GetDialogStatus(Player* player, Object* questgiver) override { + ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId()); if (questgiver->GetTypeId() == TYPEID_GAMEOBJECT) sALE->GetDialogStatus(player, questgiver->ToGameObject()); else if (questgiver->GetTypeId() == TYPEID_UNIT) @@ -577,7 +598,7 @@ class ALE_PetScript : public PetScript void OnPetAddToWorld(Pet* pet) override { - sALE->OnPetAddedToWorld(pet->GetOwner(), pet); + ALE::GetMapStateOrGlobal(pet->GetMapId(), pet->GetInstanceId())->OnPetAddedToWorld(pet->GetOwner(), pet); } }; @@ -649,7 +670,7 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerResurrect(Player* player, float /*restore_percent*/, bool /*applySickness*/) override { - sALE->OnResurrect(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnResurrect(player); } bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg) override @@ -657,7 +678,7 @@ class ALE_PlayerScript : public PlayerScript if (type != CHAT_MSG_SAY && type != CHAT_MSG_YELL && type != CHAT_MSG_EMOTE) return true; - if (!sALE->OnChat(player, type, lang, msg)) + if (!gALE->OnChat(player, type, lang, msg)) return false; return true; @@ -665,7 +686,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* target) override { - if (!sALE->OnChat(player, type, lang, msg, target)) + if (!gALE->OnChat(player, type, lang, msg, target)) return false; return true; @@ -673,7 +694,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override { - if (!sALE->OnChat(player, type, lang, msg, group)) + if (!gALE->OnChat(player, type, lang, msg, group)) return false; return true; @@ -681,7 +702,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override { - if (!sALE->OnChat(player, type, lang, msg, guild)) + if (!gALE->OnChat(player, type, lang, msg, guild)) return false; return true; @@ -689,7 +710,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel) override { - if (!sALE->OnChat(player, type, lang, msg, channel)) + if (!gALE->OnChat(player, type, lang, msg, channel)) return false; return true; @@ -697,274 +718,274 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid) override { - sALE->OnLootItem(player, item, count, lootguid); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLootItem(player, item, count, lootguid); } void OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 talentRank, uint32 spellid) override { - sALE->OnLearnTalents(player, talentId, talentRank, spellid); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLearnTalents(player, talentId, talentRank, spellid); } bool OnPlayerCanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result) override { - result = sALE->OnCanUseItem(player, proto->ItemId); + result = ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanUseItem(player, proto->ItemId); return result != EQUIP_ERR_OK ? false : true; } void OnPlayerEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool /*update*/) override { - sALE->OnEquip(player, it, bag, slot); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnEquip(player, it, bag, slot); } void OnPlayerEnterCombat(Player* player, Unit* enemy) override { - sALE->OnPlayerEnterCombat(player, enemy); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerEnterCombat(player, enemy); } void OnPlayerLeaveCombat(Player* player) override { - sALE->OnPlayerLeaveCombat(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerLeaveCombat(player); } bool OnPlayerCanRepopAtGraveyard(Player* player) override { - sALE->OnRepop(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnRepop(player); return true; } void OnPlayerQuestAbandon(Player* player, uint32 questId) override { - sALE->OnQuestAbandon(player, questId); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnQuestAbandon(player, questId); } void OnPlayerMapChanged(Player* player) override { - sALE->OnMapChanged(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnMapChanged(player); } void OnPlayerGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action) override { - sALE->HandleGossipSelectOption(player, menu_id, sender, action, ""); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, menu_id, sender, action, ""); } void OnPlayerGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code) override { - sALE->HandleGossipSelectOption(player, menu_id, sender, action, code); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, menu_id, sender, action, code); } void OnPlayerPVPKill(Player* killer, Player* killed) override { - sALE->OnPVPKill(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId(), killer->GetInstanceId())->OnPVPKill(killer, killed); } void OnPlayerCreatureKill(Player* killer, Creature* killed) override { - sALE->OnCreatureKill(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId(), killer->GetInstanceId())->OnCreatureKill(killer, killed); } void OnPlayerKilledByCreature(Creature* killer, Player* killed) override { - sALE->OnPlayerKilledByCreature(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId(), killer->GetInstanceId())->OnPlayerKilledByCreature(killer, killed); } void OnPlayerLevelChanged(Player* player, uint8 oldLevel) override { - sALE->OnLevelChanged(player, oldLevel); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLevelChanged(player, oldLevel); } void OnPlayerFreeTalentPointsChanged(Player* player, uint32 points) override { - sALE->OnFreeTalentPointsChanged(player, points); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnFreeTalentPointsChanged(player, points); } void OnPlayerTalentsReset(Player* player, bool noCost) override { - sALE->OnTalentsReset(player, noCost); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnTalentsReset(player, noCost); } void OnPlayerMoneyChanged(Player* player, int32& amount) override { - sALE->OnMoneyChanged(player, amount); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnMoneyChanged(player, amount); } void OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource) override { - sALE->OnGiveXP(player, amount, victim, xpSource); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnGiveXP(player, amount, victim, xpSource); } bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental) override { - return sALE->OnReputationChange(player, factionID, standing, incremental); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnReputationChange(player, factionID, standing, incremental); } void OnPlayerDuelRequest(Player* target, Player* challenger) override { - sALE->OnDuelRequest(target, challenger); + ALE::GetMapStateOrGlobal(challenger->GetMapId(), challenger->GetInstanceId())->OnDuelRequest(target, challenger); } void OnPlayerDuelStart(Player* player1, Player* player2) override { - sALE->OnDuelStart(player1, player2); + ALE::GetMapStateOrGlobal(player1->GetMapId(), player1->GetInstanceId())->OnDuelStart(player1, player2); } void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type) override { - sALE->OnDuelEnd(winner, loser, type); + ALE::GetMapStateOrGlobal(winner->GetMapId(), winner->GetInstanceId())->OnDuelEnd(winner, loser, type); } void OnPlayerEmote(Player* player, uint32 emote) override { - sALE->OnEmote(player, emote); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnEmote(player, emote); } void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) override { - sALE->OnTextEmote(player, textEmote, emoteNum, guid); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnTextEmote(player, textEmote, emoteNum, guid); } void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck) override { - sALE->OnPlayerSpellCast(player, spell, skipCheck); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerSpellCast(player, spell, skipCheck); } void OnPlayerLogin(Player* player) override { - sALE->OnLogin(player); + gALE->OnLogin(player); } void OnPlayerLogout(Player* player) override { - sALE->OnLogout(player); + gALE->OnLogout(player); } void OnPlayerCreate(Player* player) override { - sALE->OnCreate(player); + gALE->OnCreate(player); } void OnPlayerSave(Player* player) override { - sALE->OnSave(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnSave(player); } void OnPlayerDelete(ObjectGuid guid, uint32 /*accountId*/) override { - sALE->OnDelete(guid.GetCounter()); + gALE->OnDelete(guid.GetCounter()); } void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent) override { - sALE->OnBindToInstance(player, difficulty, mapid, permanent); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnBindToInstance(player, difficulty, mapid, permanent); } void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea) override { - sALE->OnUpdateArea(player, oldArea, newArea); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnUpdateArea(player, oldArea, newArea); } void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea) override { - sALE->OnUpdateZone(player, newZone, newArea); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnUpdateZone(player, newZone, newArea); } void OnPlayerFirstLogin(Player* player) override { - sALE->OnFirstLogin(player); + gALE->OnFirstLogin(player); } void OnPlayerLearnSpell(Player* player, uint32 spellId) override { - sALE->OnLearnSpell(player, spellId); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLearnSpell(player, spellId); } void OnPlayerAchievementComplete(Player* player, AchievementEntry const* achievement) override { - sALE->OnAchiComplete(player, achievement); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnAchiComplete(player, achievement); } void OnPlayerFfaPvpStateUpdate(Player* player, bool IsFlaggedForFfaPvp) override { - sALE->OnFfaPvpStateUpdate(player, IsFlaggedForFfaPvp); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnFfaPvpStateUpdate(player, IsFlaggedForFfaPvp); } bool OnPlayerCanInitTrade(Player* player, Player* target) override { - return sALE->OnCanInitTrade(player, target); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanInitTrade(player, target); } bool OnPlayerCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 cod, Item* item) override { - return sALE->OnCanSendMail(player, receiverGuid, mailbox, subject, body, money, cod, item); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanSendMail(player, receiverGuid, mailbox, subject, body, money, cod, item); } bool OnPlayerCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) override { - return sALE->OnCanJoinLfg(player, roles, dungeons, comment); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanJoinLfg(player, roles, dungeons, comment); } void OnPlayerQuestRewardItem(Player* player, Item* item, uint32 count) override { - sALE->OnQuestRewardItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnQuestRewardItem(player, item, count); } void OnPlayerGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) override { - sALE->OnGroupRollRewardItem(player, item, count, voteType, roll); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnGroupRollRewardItem(player, item, count, voteType, roll); } void OnPlayerCreateItem(Player* player, Item* item, uint32 count) override { - sALE->OnCreateItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCreateItem(player, item, count); } void OnPlayerStoreNewItem(Player* player, Item* item, uint32 count) override { - sALE->OnStoreNewItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnStoreNewItem(player, item, count); } void OnPlayerCompleteQuest(Player* player, Quest const* quest) override { - sALE->OnPlayerCompleteQuest(player, quest); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerCompleteQuest(player, quest); } bool OnPlayerCanGroupInvite(Player* player, std::string& memberName) override { - return sALE->OnCanGroupInvite(player, memberName); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanGroupInvite(player, memberName); } void OnPlayerBattlegroundDesertion(Player* player, const BattlegroundDesertionType type) override { - sALE->OnBattlegroundDesertion(player, type); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnBattlegroundDesertion(player, type); } void OnPlayerCreatureKilledByPet(Player* player, Creature* killed) override { - sALE->OnCreatureKilledByPet(player, killed); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCreatureKilledByPet(player, killed); } bool OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) override { - return sALE->OnPlayerCanUpdateSkill(player, skill_id); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerCanUpdateSkill(player, skill_id); } void OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step) override { - sALE->OnPlayerBeforeUpdateSkill(player, skill_id, value, max, step); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerBeforeUpdateSkill(player, skill_id, value, max, step); } void OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uint32 max, uint32 step, uint32 new_value) override { - sALE->OnPlayerUpdateSkill(player, skill_id, value, max, step, new_value); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerUpdateSkill(player, skill_id, value, max, step, new_value); } bool OnPlayerCanResurrect(Player* player) override { - return sALE->CanPlayerResurrect(player); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->CanPlayerResurrect(player); } void OnPlayerReleasedGhost(Player* player) override { - sALE->OnPlayerReleasedGhost(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerReleasedGhost(player); } }; @@ -978,7 +999,7 @@ class ALE_ServerScript : public ServerScript bool CanPacketSend(WorldSession* session, WorldPacket const& packet) override { - if (!sALE->OnPacketSend(session, packet)) + if (!gALE->OnPacketSend(session, packet)) return false; return true; @@ -986,7 +1007,7 @@ class ALE_ServerScript : public ServerScript bool CanPacketReceive(WorldSession* session, WorldPacket const& packet) override { - if (!sALE->OnPacketReceive(session, packet)) + if (!gALE->OnPacketReceive(session, packet)) return false; return true; @@ -1007,32 +1028,32 @@ class ALE_SpellSC : public SpellSC void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, GameObject* gameObjTarget) override { - sALE->OnDummyEffect(caster, spellID, effIndex, gameObjTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnDummyEffect(caster, spellID, effIndex, gameObjTarget); } void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Creature* creatureTarget) override { - sALE->OnDummyEffect(caster, spellID, effIndex, creatureTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnDummyEffect(caster, spellID, effIndex, creatureTarget); } void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Item* itemTarget) override { - sALE->OnDummyEffect(caster, spellID, effIndex, itemTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnDummyEffect(caster, spellID, effIndex, itemTarget); } void OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf) override { - sALE->OnSpellCastCancel(caster, spell, spellInfo, bySelf); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnSpellCastCancel(caster, spell, spellInfo, bySelf); } void OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck) override { - sALE->OnSpellCast(caster, spell, spellInfo, skipCheck); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnSpellCast(caster, spell, spellInfo, skipCheck); } void OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo) override { - sALE->OnSpellPrepare(caster, spell, spellInfo); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnSpellPrepare(caster, spell, spellInfo); } }; @@ -1043,27 +1064,27 @@ class ALE_VehicleScript : public VehicleScript void OnInstall(Vehicle* veh) override { - sALE->OnInstall(veh); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnInstall(veh); } void OnUninstall(Vehicle* veh) override { - sALE->OnUninstall(veh); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnUninstall(veh); } void OnInstallAccessory(Vehicle* veh, Creature* accessory) override { - sALE->OnInstallAccessory(veh, accessory); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnInstallAccessory(veh, accessory); } void OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId) override { - sALE->OnAddPassenger(veh, passenger, seatId); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnAddPassenger(veh, passenger, seatId); } void OnRemovePassenger(Vehicle* veh, Unit* passenger) override { - sALE->OnRemovePassenger(veh, passenger); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnRemovePassenger(veh, passenger); } }; @@ -1079,8 +1100,11 @@ class ALE_WorldObjectScript : public WorldObjectScript void OnWorldObjectDestroy(WorldObject* object) override { - delete object->ALEEvents; - object->ALEEvents = nullptr; + if (object->ALEEvents) + { + delete object->ALEEvents; + object->ALEEvents = nullptr; + } } void OnWorldObjectCreate(WorldObject* object) override @@ -1088,15 +1112,26 @@ class ALE_WorldObjectScript : public WorldObjectScript object->ALEEvents = nullptr; } - void OnWorldObjectSetMap(WorldObject* object, Map* /*map*/) override + void OnWorldObjectSetMap(WorldObject* object, Map* map) override { if (!object->ALEEvents) - object->ALEEvents = new ALEEventProcessor(&ALE::GALE, object); + { + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) + { + ALE** stateSlot = ALE::GetMapStateSlot(map->GetId(), map->GetInstanceId()); + object->ALEEvents = new ALEEventProcessor(stateSlot, object); + } + else + { + object->ALEEvents = new ALEEventProcessor(&ALE::GALE, object); + } + } } void OnWorldObjectUpdate(WorldObject* object, uint32 diff) override { - object->ALEEvents->Update(diff); + if (object->ALEEvents) + object->ALEEvents->Update(diff); } }; @@ -1118,7 +1153,7 @@ class ALE_WorldScript : public WorldScript void OnOpenStateChange(bool open) override { - sALE->OnOpenStateChange(open); + gALE->OnOpenStateChange(open); } void OnBeforeConfigLoad(bool reload) override @@ -1131,37 +1166,37 @@ class ALE_WorldScript : public WorldScript ALE::Initialize(); } - sALE->OnConfigLoad(reload, true); + gALE->OnConfigLoad(reload, true); } void OnAfterConfigLoad(bool reload) override { - sALE->OnConfigLoad(reload, false); + gALE->OnConfigLoad(reload, false); } void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask) override { - sALE->OnShutdownInitiate(code, mask); + gALE->OnShutdownInitiate(code, mask); } void OnShutdownCancel() override { - sALE->OnShutdownCancel(); + gALE->OnShutdownCancel(); } void OnUpdate(uint32 diff) override { - sALE->OnWorldUpdate(diff); + gALE->OnWorldUpdate(diff); } void OnStartup() override { - sALE->OnStartup(); + gALE->OnStartup(); } void OnShutdown() override { - sALE->OnShutdown(); + gALE->OnShutdown(); } void OnAfterUnloadAllMaps() override @@ -1173,8 +1208,9 @@ class ALE_WorldScript : public WorldScript { ///- Run ALE scripts. // in multithread foreach: run scripts - sALE->RunScripts(); - sALE->OnConfigLoad(false, false); // Must be done after ALE is initialized and scripts have run. + gALE->RunScripts(); + ALE::RunScriptsOnAllMapStates(); + gALE->OnConfigLoad(false, false); // Must be done after ALE is initialized and scripts have run. } }; @@ -1190,22 +1226,22 @@ class ALE_TicketScript : public TicketScript void OnTicketCreate(GmTicket* ticket) override { - sALE->OnTicketCreate(ticket); + gALE->OnTicketCreate(ticket); } void OnTicketUpdateLastChange(GmTicket* ticket) override { - sALE->OnTicketUpdateLastChange(ticket); + gALE->OnTicketUpdateLastChange(ticket); } void OnTicketClose(GmTicket* ticket) override { - sALE->OnTicketClose(ticket); + gALE->OnTicketClose(ticket); } void OnTicketResolve(GmTicket* ticket) override { - sALE->OnTicketResolve(ticket); + gALE->OnTicketResolve(ticket); } }; @@ -1217,6 +1253,7 @@ class ALE_UnitScript : public UnitScript void OnAuraApply(Unit* unit, Aura* aura) override { if (!unit || !aura) return; + ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId(), unit->GetInstanceId()); if (unit->IsPlayer()) sALE->OnPlayerAuraApply(unit->ToPlayer(), aura); @@ -1231,6 +1268,7 @@ class ALE_UnitScript : public UnitScript void OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode) override { if (!unit || !aurApp->GetBase()) return; + ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId(), unit->GetInstanceId()); if (unit->IsPlayer()) sALE->OnPlayerAuraRemove(unit->ToPlayer(), aurApp->GetBase(), mode); @@ -1245,6 +1283,7 @@ class ALE_UnitScript : public UnitScript void OnHeal(Unit* healer, Unit* receiver, uint32& gain) override { if (!receiver || !healer) return; + ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId(), healer->GetInstanceId()); if (healer->IsPlayer()) sALE->OnPlayerHeal(healer->ToPlayer(), receiver, gain); @@ -1259,6 +1298,7 @@ class ALE_UnitScript : public UnitScript void OnDamage(Unit* attacker, Unit* receiver, uint32& damage) override { if (!attacker || !receiver) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerDamage(attacker->ToPlayer(), receiver, damage); @@ -1273,6 +1313,7 @@ class ALE_UnitScript : public UnitScript void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo) override { if (!target || !attacker) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerModifyPeriodicDamageAurasTick(attacker->ToPlayer(), target, damage, spellInfo); @@ -1287,6 +1328,7 @@ class ALE_UnitScript : public UnitScript void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage) override { if (!target || !attacker) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerModifyMeleeDamage(attacker->ToPlayer(), target, damage); @@ -1301,6 +1343,7 @@ class ALE_UnitScript : public UnitScript void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage, SpellInfo const* spellInfo) override { if (!target || !attacker) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerModifySpellDamageTaken(attacker->ToPlayer(), target, damage, spellInfo); @@ -1315,6 +1358,7 @@ class ALE_UnitScript : public UnitScript void ModifyHealReceived(Unit* target, Unit* healer, uint32& heal, SpellInfo const* spellInfo) override { if (!target || !healer) return; + ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId(), healer->GetInstanceId()); if (healer->IsPlayer()) sALE->OnPlayerModifyHealReceived(healer->ToPlayer(), target, heal, spellInfo); @@ -1329,6 +1373,7 @@ class ALE_UnitScript : public UnitScript uint32 DealDamage(Unit* AttackerUnit, Unit* pVictim, uint32 damage, DamageEffectType damagetype) override { if (!AttackerUnit || !pVictim) return damage; + ALE* sALE = ALE::GetMapStateOrGlobal(AttackerUnit->GetMapId(), AttackerUnit->GetInstanceId()); if (AttackerUnit->IsPlayer()) return sALE->OnPlayerDealDamage(AttackerUnit->ToPlayer(), pVictim, damage, damagetype); diff --git a/src/LuaEngine/ALEConfig.cpp b/src/LuaEngine/ALEConfig.cpp index e3eca213bd..d800fcf557 100644 --- a/src/LuaEngine/ALEConfig.cpp +++ b/src/LuaEngine/ALEConfig.cpp @@ -1,4 +1,8 @@ #include "ALEConfig.h" +#include "ALEUtility.h" +#include +#include +#include ALEConfig& ALEConfig::GetInstance() { @@ -13,6 +17,7 @@ ALEConfig::ALEConfig() : ConfigValueCache(ALEConfigValues::CONF void ALEConfig::Initialize(bool reload) { ConfigValueCache::Initialize(reload); + TokenizeAllowedMaps(); } void ALEConfig::BuildConfigCache() @@ -21,10 +26,71 @@ void ALEConfig::BuildConfigCache() SetConfigValue(ALEConfigValues::TRACEBACK_ENABLED, "ALE.TraceBack", "false"); SetConfigValue(ALEConfigValues::AUTORELOAD_ENABLED, "ALE.AutoReload", "false"); SetConfigValue(ALEConfigValues::BYTECODE_CACHE_ENABLED, "ALE.BytecodeCache", "false"); + SetConfigValue(ALEConfigValues::COMPATIBILITY_MODE, "ALE.CompatibilityMode", "true"); SetConfigValue(ALEConfigValues::SCRIPT_PATH, "ALE.ScriptPath", "lua_scripts"); SetConfigValue(ALEConfigValues::REQUIRE_PATH, "ALE.RequirePaths", ""); SetConfigValue(ALEConfigValues::REQUIRE_CPATH, "ALE.RequireCPaths", ""); + SetConfigValue(ALEConfigValues::ONLY_ON_MAPS, "ALE.OnlyOnMaps", ""); SetConfigValue(ALEConfigValues::AUTORELOAD_INTERVAL, "ALE.AutoReloadInterval", 1); } + +bool ALEConfig::ShouldMapLoadALE(uint32 mapId) const +{ + if (m_allowedMaps.empty()) + return true; + return m_allowedMaps.find(mapId) != m_allowedMaps.end(); +} + +bool ALEConfig::ShouldMapLoadALEByFolderName(const std::string& folderName, uint32 mapId) const +{ + std::string digits; + for (char c : folderName) + { + if (std::isdigit(static_cast(c))) + digits += c; + else + break; + } + + if (digits.empty()) + return true; + + try + { + uint32 folderMapId = std::stoul(digits); + return folderMapId == mapId; + } + catch (std::exception&) + { + return true; + } +} + +void ALEConfig::TokenizeAllowedMaps() +{ + m_allowedMaps.clear(); + + std::istringstream maps(static_cast(GetConfigValue(ALEConfigValues::ONLY_ON_MAPS))); + std::string mapIdStr; + while (std::getline(maps, mapIdStr, ',')) + { + mapIdStr.erase(std::remove_if(mapIdStr.begin(), mapIdStr.end(), [](char c) { + return std::isspace(static_cast(c)); + }), mapIdStr.end()); + + if (mapIdStr.empty()) + continue; + + try + { + uint32 mapId = std::stoul(mapIdStr); + m_allowedMaps.emplace(mapId); + } + catch (std::exception&) + { + ALE_LOG_ERROR("[ALEConfig]: Invalid map ID in ALE.OnlyOnMaps: '{}'", mapIdStr); + } + } +} diff --git a/src/LuaEngine/ALEConfig.h b/src/LuaEngine/ALEConfig.h index b413b4a451..11c961355d 100644 --- a/src/LuaEngine/ALEConfig.h +++ b/src/LuaEngine/ALEConfig.h @@ -2,6 +2,7 @@ #define ALE_CONFIG_HPP #include "ConfigValueCache.h" +#include enum class ALEConfigValues : uint32 { @@ -10,11 +11,13 @@ enum class ALEConfigValues : uint32 TRACEBACK_ENABLED, AUTORELOAD_ENABLED, BYTECODE_CACHE_ENABLED, + COMPATIBILITY_MODE, // String SCRIPT_PATH, REQUIRE_PATH, REQUIRE_CPATH, + ONLY_ON_MAPS, // Number AUTORELOAD_INTERVAL, @@ -33,6 +36,7 @@ class ALEConfig final : public ConfigValueCache bool IsTraceBackEnabled() const { return GetConfigValue(ALEConfigValues::TRACEBACK_ENABLED); } bool IsAutoReloadEnabled() const { return GetConfigValue(ALEConfigValues::AUTORELOAD_ENABLED); } bool IsByteCodeCacheEnabled() const { return GetConfigValue(ALEConfigValues::BYTECODE_CACHE_ENABLED); } + bool IsCompatibilityModeEnabled() const { return GetConfigValue(ALEConfigValues::COMPATIBILITY_MODE); } std::string_view GetScriptPath() const { return GetConfigValue(ALEConfigValues::SCRIPT_PATH); } std::string_view GetRequirePath() const { return GetConfigValue(ALEConfigValues::REQUIRE_PATH); } @@ -40,6 +44,9 @@ class ALEConfig final : public ConfigValueCache uint32 GetAutoReloadInterval() const { return GetConfigValue(ALEConfigValues::AUTORELOAD_INTERVAL); } + bool ShouldMapLoadALE(uint32 mapId) const; + bool ShouldMapLoadALEByFolderName(const std::string& folderName, uint32 mapId) const; + protected: void BuildConfigCache() override; @@ -48,6 +55,10 @@ class ALEConfig final : public ConfigValueCache ~ALEConfig() = default; ALEConfig(const ALEConfig&) = delete; ALEConfig& operator=(const ALEConfig&) = delete; + + void TokenizeAllowedMaps(); + + std::unordered_set m_allowedMaps; }; #endif // ALE_CONFIG_H \ No newline at end of file diff --git a/src/LuaEngine/ALECreatureAI.h b/src/LuaEngine/ALECreatureAI.h index cb9ccdae7c..3b584d0d07 100644 --- a/src/LuaEngine/ALECreatureAI.h +++ b/src/LuaEngine/ALECreatureAI.h @@ -17,8 +17,10 @@ struct ALECreatureAI : ScriptedAI bool justSpawned; // used to delay movementinform hook (WP hook) std::vector< std::pair > movepoints; + ALE* sALE; - ALECreatureAI(Creature* creature) : ScriptedAI(creature), justSpawned(true) + ALECreatureAI(Creature* creature) : ScriptedAI(creature), justSpawned(true), + sALE(ALE::GetMapStateOrGlobal(creature->GetMapId())) { } ~ALECreatureAI() { } diff --git a/src/LuaEngine/ALEEventMgr.cpp b/src/LuaEngine/ALEEventMgr.cpp index f90cee3167..d9d3ffd5f8 100644 --- a/src/LuaEngine/ALEEventMgr.cpp +++ b/src/LuaEngine/ALEEventMgr.cpp @@ -27,12 +27,17 @@ ALEEventProcessor::ALEEventProcessor(ALE** _E, WorldObject* _obj) : m_time(0), o ALEEventProcessor::~ALEEventProcessor() { // can be called from multiple threads + if (*E) + { + ALE::Guard guard((*E)->GetStateLock()); + RemoveEvents_internal(); + } + else { - LOCK_ALE; RemoveEvents_internal(); } - if (obj && ALE::IsInitialized()) + if (obj && ALE::IsInitialized() && *E && (*E)->eventMgr) { EventMgr::Guard guard((*E)->eventMgr->GetLock()); (*E)->eventMgr->processors.erase(this); @@ -57,8 +62,10 @@ void ALEEventProcessor::Update(uint32 diff) if (!remove) AddEvent(luaEvent); // Reschedule before calling incase RemoveEvents used - // Call the timed event - (*E)->OnTimedEvent(luaEvent->funcRef, delay, luaEvent->repeats ? luaEvent->repeats-- : luaEvent->repeats, obj); + // Call the timed event using the event's own state slot + ALE** slot = luaEvent->stateSlot; + if (slot && *slot && (*slot)->HasLuaState()) + (*slot)->OnTimedEvent(luaEvent->funcRef, delay, luaEvent->repeats ? luaEvent->repeats-- : luaEvent->repeats, obj); if (!remove) continue; @@ -79,13 +86,6 @@ void ALEEventProcessor::SetStates(LuaEventState state) void ALEEventProcessor::RemoveEvents_internal() { - //if (!final) - //{ - // for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it) - // it->second->to_Abort = true; - // return; - //} - for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it) RemoveEvent(it->second); @@ -108,18 +108,19 @@ void ALEEventProcessor::AddEvent(LuaEvent* luaEvent) eventMap[luaEvent->funcRef] = luaEvent; } -void ALEEventProcessor::AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats) +void ALEEventProcessor::AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats, ALE** stateSlot) { - AddEvent(new LuaEvent(funcRef, min, max, repeats)); + AddEvent(new LuaEvent(funcRef, min, max, repeats, stateSlot)); } void ALEEventProcessor::RemoveEvent(LuaEvent* luaEvent) { - // Unreference if should and if ALE was not yet uninitialized and if the lua state still exists - if (luaEvent->state != LUAEVENT_STATE_ERASE && ALE::IsInitialized() && (*E)->HasLuaState()) + // Unreference using the event's own state slot + ALE** slot = luaEvent->stateSlot; + if (luaEvent->state != LUAEVENT_STATE_ERASE && ALE::IsInitialized() && slot && *slot && (*slot)->HasLuaState()) { // Free lua function ref - luaL_unref((*E)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); + luaL_unref((*slot)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); } delete luaEvent; } diff --git a/src/LuaEngine/ALEEventMgr.h b/src/LuaEngine/ALEEventMgr.h index 5302ecead2..a4e2c73638 100644 --- a/src/LuaEngine/ALEEventMgr.h +++ b/src/LuaEngine/ALEEventMgr.h @@ -28,8 +28,8 @@ enum LuaEventState struct LuaEvent { - LuaEvent(int _funcRef, uint32 _min, uint32 _max, uint32 _repeats) : - min(_min), max(_max), delay(0), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN) + LuaEvent(int _funcRef, uint32 _min, uint32 _max, uint32 _repeats, ALE** _stateSlot) : + min(_min), max(_max), delay(0), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN), stateSlot(_stateSlot) { } @@ -50,6 +50,7 @@ struct LuaEvent uint32 repeats; // Amount of repeats to make, 0 for infinite int funcRef; // Lua function reference ID, also used as event ID LuaEventState state; // State for next call + ALE** stateSlot; }; class ALEEventProcessor @@ -68,7 +69,7 @@ class ALEEventProcessor void SetStates(LuaEventState state); // set the event to be removed when executing void SetState(int eventId, LuaEventState state); - void AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats); + void AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats, ALE** stateSlot); EventMap eventMap; private: diff --git a/src/LuaEngine/ALEInstanceAI.cpp b/src/LuaEngine/ALEInstanceAI.cpp index ea32f2feaa..93a206a1ea 100644 --- a/src/LuaEngine/ALEInstanceAI.cpp +++ b/src/LuaEngine/ALEInstanceAI.cpp @@ -12,6 +12,7 @@ void ALEInstanceAI::Initialize() { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); ASSERT(!sALE->HasInstanceData(instance)); @@ -26,6 +27,7 @@ void ALEInstanceAI::Initialize() void ALEInstanceAI::Load(const char* data) { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); // If we get passed NULL (i.e. `Reload` was called) then use // the last known save data (or maybe just an empty string). @@ -108,6 +110,7 @@ void ALEInstanceAI::Load(const char* data) const char* ALEInstanceAI::Save() const { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -146,6 +149,7 @@ const char* ALEInstanceAI::Save() const uint32 ALEInstanceAI::GetData(uint32 key) const { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -168,6 +172,7 @@ uint32 ALEInstanceAI::GetData(uint32 key) const void ALEInstanceAI::SetData(uint32 key, uint32 value) { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -188,6 +193,7 @@ void ALEInstanceAI::SetData(uint32 key, uint32 value) uint64 ALEInstanceAI::GetData64(uint32 key) const { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -210,6 +216,7 @@ uint64 ALEInstanceAI::GetData64(uint32 key) const void ALEInstanceAI::SetData64(uint32 key, uint64 value) { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) diff --git a/src/LuaEngine/ALEInstanceAI.h b/src/LuaEngine/ALEInstanceAI.h index ebc5037db0..6ee03baa5c 100644 --- a/src/LuaEngine/ALEInstanceAI.h +++ b/src/LuaEngine/ALEInstanceAI.h @@ -53,7 +53,7 @@ class ALEInstanceAI : public InstanceData private: // The last save data to pass through this class, // either through `Load` or `Save`. - std::string lastSaveData; + mutable std::string lastSaveData; public: ALEInstanceAI(Map* map) : InstanceData(map) @@ -72,8 +72,8 @@ class ALEInstanceAI : public InstanceData { return Save(); } - const char* Save() const; + const char* Save() const; /* * Calls `Load` with the last save data that was passed to @@ -100,6 +100,8 @@ class ALEInstanceAI : public InstanceData */ void Update(uint32 diff) override { + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + // If ALE is reloaded, it will be missing our instance data. // Reload here instead of waiting for the next hook call (possibly never). // This avoids having to have an empty Update hook handler just to trigger the reload. @@ -111,22 +113,22 @@ class ALEInstanceAI : public InstanceData bool IsEncounterInProgress() const override { - return sALE->OnCheckEncounterInProgress(const_cast(this)); + return ALE::GetMapStateOrGlobal(instance->GetId())->OnCheckEncounterInProgress(const_cast(this)); } void OnPlayerEnter(Player* player) override { - sALE->OnPlayerEnterInstance(this, player); + ALE::GetMapStateOrGlobal(instance->GetId())->OnPlayerEnterInstance(this, player); } void OnGameObjectCreate(GameObject* gameobject) override { - sALE->OnGameObjectCreate(this, gameobject); + ALE::GetMapStateOrGlobal(instance->GetId())->OnGameObjectCreate(this, gameobject); } void OnCreatureCreate(Creature* creature) override { - sALE->OnCreatureCreate(this, creature); + ALE::GetMapStateOrGlobal(instance->GetId())->OnCreatureCreate(this, creature); } }; diff --git a/src/LuaEngine/ALETemplate.h b/src/LuaEngine/ALETemplate.h index a8d6fc497a..de0d89bcaa 100644 --- a/src/LuaEngine/ALETemplate.h +++ b/src/LuaEngine/ALETemplate.h @@ -68,7 +68,7 @@ class ALEObject // Get wrapped object pointer void* GetObj() const { return object; } // Returns whether the object is valid or not - bool IsValid() const { return !callstackid || callstackid == sALE->GetCallstackId(); } + bool IsValid() const { return !callstackid || callstackid == ALE::GALE->GetCallstackId(); } // Returns whether the object can be invalidated or not bool CanInvalidate() const { return _invalidate; } // Returns pointer to the wrapped object's type name @@ -87,7 +87,7 @@ class ALEObject ASSERT(!valid || (valid && object)); if (valid) if (CanInvalidate()) - callstackid = sALE->GetCallstackId(); + callstackid = ALE::GALE->GetCallstackId(); else callstackid = 0; else diff --git a/src/LuaEngine/HttpManager.cpp b/src/LuaEngine/HttpManager.cpp index f7079cf3c9..af3024bdb9 100644 --- a/src/LuaEngine/HttpManager.cpp +++ b/src/LuaEngine/HttpManager.cpp @@ -11,8 +11,9 @@ extern "C" #include "HttpManager.h" #include "LuaEngine.h" -HttpWorkItem::HttpWorkItem(int funcRef, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string& contentType, const httplib::Headers& headers) +HttpWorkItem::HttpWorkItem(int funcRef, ALE* state, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string& contentType, const httplib::Headers& headers) : funcRef(funcRef), + state(state), httpVerb(httpVerb), url(url), body(body), @@ -20,8 +21,9 @@ HttpWorkItem::HttpWorkItem(int funcRef, const std::string& httpVerb, const std:: headers(headers) { } -HttpResponse::HttpResponse(int funcRef, int statusCode, const std::string& body, const httplib::Headers& headers) +HttpResponse::HttpResponse(int funcRef, ALE* state, int statusCode, const std::string& body, const httplib::Headers& headers) : funcRef(funcRef), + state(state), statusCode(statusCode), body(body), headers(headers) @@ -166,7 +168,7 @@ void HttpManager::HttpWorkerThread() res = DoRequest(cli2, req, path); } - responseQueue.push(new HttpResponse(req->funcRef, res->status, res->body, res->headers)); + responseQueue.push(new HttpResponse(req->funcRef, req->state, res->status, res->body, res->headers)); } catch (const std::exception& ex) { @@ -250,7 +252,7 @@ void HttpManager::HandleHttpResponses() LOCK_ALE; - lua_State* L = ALE::GALE->L; + lua_State* L = res->state->L; // Get function lua_rawgeti(L, LUA_REGISTRYINDEX, res->funcRef); @@ -266,7 +268,7 @@ void HttpManager::HandleHttpResponses() } // Call function - ALE::GALE->ExecuteCall(3, 0); + res->state->ExecuteCall(3, 0); luaL_unref(L, LUA_REGISTRYINDEX, res->funcRef); diff --git a/src/LuaEngine/HttpManager.h b/src/LuaEngine/HttpManager.h index cab17a4466..412739fe22 100644 --- a/src/LuaEngine/HttpManager.h +++ b/src/LuaEngine/HttpManager.h @@ -6,12 +6,15 @@ #include "libs/httplib.h" #include "libs/rigtorp/SPSCQueue.h" +class ALE; + struct HttpWorkItem { public: - HttpWorkItem(int funcRef, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string &contentType, const httplib::Headers& headers); + HttpWorkItem(int funcRef, ALE* state, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string &contentType, const httplib::Headers& headers); int funcRef; + ALE* state; std::string httpVerb; std::string url; std::string body; @@ -22,9 +25,10 @@ struct HttpWorkItem struct HttpResponse { public: - HttpResponse(int funcRef, int statusCode, const std::string& body, const httplib::Headers& headers); + HttpResponse(int funcRef, ALE* state, int statusCode, const std::string& body, const httplib::Headers& headers); int funcRef; + ALE* state; int statusCode; std::string body; httplib::Headers headers; diff --git a/src/LuaEngine/LuaEngine.cpp b/src/LuaEngine/LuaEngine.cpp index c647d689a5..96ae136088 100644 --- a/src/LuaEngine/LuaEngine.cpp +++ b/src/LuaEngine/LuaEngine.cpp @@ -52,6 +52,10 @@ bool ALE::initialized = false; ALE::LockType ALE::lock; std::unique_ptr ALE::fileWatcher; +// Multistate handling +std::map ALE::g_states; +std::shared_mutex ALE::g_states_mutex; + // Global bytecode cache that survives ALE reloads static std::unordered_map globalBytecodeCache; static std::unordered_map timestampCache; @@ -75,7 +79,7 @@ void ALE::Initialize() initialized = true; // Create global ALE - GALE = new ALE(); + GALE = new ALE(nullptr, ALE_GLOBAL_STATE); // Start file watcher if enabled if (ALEConfig::GetInstance().IsAutoReloadEnabled()) @@ -98,6 +102,15 @@ void ALE::Uninitialize() fileWatcher.reset(); } + { + std::unique_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + { + delete state; + } + g_states.clear(); + } + delete GALE; GALE = NULL; @@ -110,6 +123,38 @@ void ALE::Uninitialize() initialized = false; } +ALE** ALE::CreateMapState(uint32 mapId, uint32 instanceId) +{ + if (!ALEConfig::GetInstance().ShouldMapLoadALE(mapId)) + return nullptr; + + ALE** slotPtr; + uint64 key = ((uint64)mapId << 32) | instanceId; + { + std::unique_lock lock(g_states_mutex); + ASSERT(g_states.find(key) == g_states.end()); + auto& slot = g_states[key]; + slot = nullptr; + slotPtr = &slot; + slot = new ALE(slotPtr, mapId, instanceId); + } + + (*slotPtr)->RunScripts(); + return slotPtr; +} + +void ALE::DestroyMapState(uint32 mapId, uint32 instanceId) +{ + std::unique_lock lock(g_states_mutex); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); + if (it != g_states.end()) + { + delete it->second; + g_states.erase(it); + } +} + void ALE::LoadScriptPaths() { uint32 oldMSTime = ALEUtil::GetCurrTime(); @@ -132,7 +177,7 @@ void ALE::LoadScriptPaths() lua_requirepath.clear(); lua_requirecpath.clear(); - GetScripts(lua_folderpath); + GetScripts(lua_folderpath, 0); // append our custom require paths and cpaths if the config variables are not empty if (!lua_path_extra.empty()) @@ -162,26 +207,40 @@ void ALE::_ReloadALE() ChatHandler(nullptr).SendGMText(SERVER_MSG_STRING, "Reloading ALE..."); // Remove all timed events - sALE->eventMgr->SetStates(LUAEVENT_STATE_ERASE); + ALE::GALE->eventMgr->SetStates(LUAEVENT_STATE_ERASE); // Close lua - sALE->CloseLua(); + ALE::GALE->CloseLua(); // Reload script paths LoadScriptPaths(); // Open new lua and libaraies - sALE->OpenLua(); + ALE::GALE->OpenLua(); // Run scripts from laoded paths - sALE->RunScripts(); + ALE::GALE->RunScripts(); + { + std::shared_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + { + state->eventMgr->SetStates(LUAEVENT_STATE_ERASE); + state->CloseLua(); + state->OpenLua(); + state->RunScripts(); + } + } + reload = false; } -ALE::ALE() : +ALE::ALE(ALE** _selfPtr, uint32 mapId, uint32 instanceId) : +stateMapId(mapId), +stateInstanceId(instanceId), event_level(0), push_counter(0), +selfPtr(_selfPtr), L(NULL), eventMgr(NULL), @@ -215,11 +274,8 @@ CreatureUniqueBindings(NULL) OpenLua(); - // Replace this with map insert if making multithread version - - // Set event manager. Must be after setting sALE - // on multithread have a map of state pointers and here insert this pointer to the map and then save a pointer of that pointer to the EventMgr - eventMgr = new EventMgr(&ALE::GALE); + ALE** evtPtr = selfPtr ? selfPtr : &ALE::GALE; + eventMgr = new EventMgr(evtPtr); } ALE::~ALE() @@ -614,7 +670,7 @@ int ALE::LoadCompiledScript(lua_State* L, const std::string& filepath) } // Finds lua script files from given path (including subdirectories) and pushes them to scripts -void ALE::GetScripts(std::string path) +void ALE::GetScripts(std::string path, uint32 mapId) { ALE_LOG_DEBUG("[ALE]: GetScripts from path `{}`", path); @@ -650,7 +706,10 @@ void ALE::GetScripts(std::string path) // load subfolder if (boost::filesystem::is_directory(dir_iter->status())) { - GetScripts(fullpath); + std::string folderName = dir_iter->path().filename().generic_string(); + if (!ALEConfig::GetInstance().ShouldMapLoadALEByFolderName(folderName, mapId)) + continue; + GetScripts(fullpath, mapId); continue; } @@ -700,6 +759,11 @@ void ALE::RunScripts() int modules = lua_gettop(L); for (ScriptList::iterator it = scripts.begin(); it != scripts.end(); ++it) { + // Filter by map-prefixed subdirectory + std::string folderName = boost::filesystem::path(it->modulepath).filename().generic_string(); + if (!ALEConfig::GetInstance().ShouldMapLoadALEByFolderName(folderName, stateMapId)) + continue; + // Check that no duplicate names exist if (loaded.find(it->filename) != loaded.end()) { @@ -837,7 +901,7 @@ int ALE::StackTrace(lua_State *_L) // dirty stack? // Stack: errmsg, debug, tracemsg - sALE->OnError(std::string(lua_tostring(_L, -1))); + ALE::GALE->OnError(std::string(lua_tostring(_L, -1))); return 1; } diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index a21640d0e4..e738b60202 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -28,6 +28,8 @@ #include "ALEConfig.h" #include #include +#include +#include #include #include #include @@ -104,6 +106,8 @@ struct LuaScript #define ALE_STATE_PTR "ALE State Ptr" #define LOCK_ALE ALE::Guard __guard(ALE::GetLock()) +#define LOCK_ALE_STATE ALE::Guard __guard(this->GetStateLock()) +#define ALE_GLOBAL_STATE (uint32)(-1) #define ALE_GAME_API AC_GAME_API @@ -118,7 +122,23 @@ class ALE_GAME_API ALE const std::string& GetRequirePath() const { return lua_requirepath; } const std::string& GetRequireCPath() const { return lua_requirecpath; } + LockType& GetStateLock() { return stateLock; } + uint32 GetStateMapId() const { return stateMapId; } + uint32 GetStateInstanceId() const { return stateInstanceId; } + ALE** GetSelfPtr() { return selfPtr ? selfPtr : &ALE::GALE; } + + static void RunScriptsOnAllMapStates() + { + std::shared_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + state->RunScripts(); + } + private: + LockType stateLock; + uint32 stateMapId; + uint32 stateInstanceId; + static bool reload; static bool initialized; static LockType lock; @@ -134,6 +154,10 @@ class ALE_GAME_API ALE static std::string lua_requirepath; static std::string lua_requirecpath; + // Per-map states. std::map used for pointer stability on insert/erase. + static std::map g_states; + static std::shared_mutex g_states_mutex; + // A counter for lua event stacks that occur (see event_level). // This is used to determine whether an object belongs to the current call stack or not. // 0 is reserved for always belonging to the call stack @@ -152,7 +176,9 @@ class ALE_GAME_API ALE // Map from map ID -> Lua table ref std::unordered_map continentDataRefs; - ALE(); + ALE** selfPtr; + + ALE(ALE** selfPtr = nullptr, uint32 mapId = ALE_GLOBAL_STATE, uint32 instanceId = 0); ~ALE(); // Prevent copy @@ -169,7 +195,7 @@ class ALE_GAME_API ALE // This is called on world update to reload ALE static void _ReloadALE(); static void LoadScriptPaths(); - static void GetScripts(std::string path); + static void GetScripts(std::string path, uint32 mapId = 0); static void AddScriptPath(std::string filename, const std::string& fullpath); static int LoadCompiledScript(lua_State* L, const std::string& filepath); static std::time_t GetFileModTime(const std::string& filepath); @@ -268,6 +294,39 @@ class ALE_GAME_API ALE static void ReloadALE() { LOCK_ALE; reload = true; } static LockType& GetLock() { return lock; }; static bool IsInitialized() { return initialized; } + + static ALE* GetMapState(uint32 mapId, uint32 instanceId = 0) + { + std::shared_lock lock(g_states_mutex); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); + return it != g_states.end() ? it->second : nullptr; + } + + static ALE* GetMapStateOrGlobal(uint32 mapId, uint32 instanceId = 0) + { + std::shared_lock lock(g_states_mutex); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); + return it != g_states.end() ? it->second : GALE; + } + + static ALE** CreateMapState(uint32 mapId, uint32 instanceId = 0); + static void DestroyMapState(uint32 mapId, uint32 instanceId = 0); + + // Returns a stable pointer-to-pointer for the map state slot, for use by ALEEventProcessor. + static ALE** GetMapStateSlot(uint32 mapId, uint32 instanceId = 0) + { + uint64 key = ((uint64)mapId << 32) | instanceId; + { + std::shared_lock lock(g_states_mutex); + auto it = g_states.find(key); + if (it != g_states.end()) + return &it->second; + } + return CreateMapState(mapId, instanceId); + } + // Never returns nullptr static ALE* GetALE(lua_State* L) { @@ -623,5 +682,5 @@ template<> Object* ALE::CHECKOBJ(lua_State* L, int narg, bool error); template<> WorldObject* ALE::CHECKOBJ(lua_State* L, int narg, bool error); template<> ALEObject* ALE::CHECKOBJ(lua_State* L, int narg, bool error); -#define sALE ALE::GALE +#define gALE ALE::GALE #endif diff --git a/src/LuaEngine/hooks/AllCreatureHooks.cpp b/src/LuaEngine/hooks/AllCreatureHooks.cpp index f32fe110e1..bb3f85dfe8 100644 --- a/src/LuaEngine/hooks/AllCreatureHooks.cpp +++ b/src/LuaEngine/hooks/AllCreatureHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!AllCreatureEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!AllCreatureEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnAllCreatureAddToWorld(Creature* creature) { diff --git a/src/LuaEngine/hooks/BattleGroundHooks.cpp b/src/LuaEngine/hooks/BattleGroundHooks.cpp index ec70cf5a15..5d3ee57a6a 100644 --- a/src/LuaEngine/hooks/BattleGroundHooks.cpp +++ b/src/LuaEngine/hooks/BattleGroundHooks.cpp @@ -18,7 +18,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!BGEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnBGStart(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId) { diff --git a/src/LuaEngine/hooks/CreatureHooks.cpp b/src/LuaEngine/hooks/CreatureHooks.cpp index 9fca834e48..3cf92a9373 100644 --- a/src/LuaEngine/hooks/CreatureHooks.cpp +++ b/src/LuaEngine/hooks/CreatureHooks.cpp @@ -21,7 +21,7 @@ using namespace Hooks; if (!CreatureEventBindings->HasBindingsFor(entry_key))\ if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, CREATURE, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -31,7 +31,7 @@ using namespace Hooks; if (!CreatureEventBindings->HasBindingsFor(entry_key))\ if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, Creature* pTarget) { diff --git a/src/LuaEngine/hooks/GameObjectHooks.cpp b/src/LuaEngine/hooks/GameObjectHooks.cpp index 7dd8508f4f..b25f300ee5 100644 --- a/src/LuaEngine/hooks/GameObjectHooks.cpp +++ b/src/LuaEngine/hooks/GameObjectHooks.cpp @@ -20,7 +20,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!GameObjectEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -28,7 +28,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!GameObjectEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, GameObject* pTarget) { diff --git a/src/LuaEngine/hooks/GossipHooks.cpp b/src/LuaEngine/hooks/GossipHooks.cpp index 5fa324516f..aa0fad089a 100644 --- a/src/LuaEngine/hooks/GossipHooks.cpp +++ b/src/LuaEngine/hooks/GossipHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!BINDINGS->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(BINDINGS, EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!BINDINGS->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE bool ALE::OnGossipHello(Player* pPlayer, GameObject* pGameObject) { diff --git a/src/LuaEngine/hooks/InstanceHooks.cpp b/src/LuaEngine/hooks/InstanceHooks.cpp index 113ca2b348..56137b2c59 100644 --- a/src/LuaEngine/hooks/InstanceHooks.cpp +++ b/src/LuaEngine/hooks/InstanceHooks.cpp @@ -21,7 +21,7 @@ using namespace Hooks; auto instanceKey = EntryKey(EVENT, AI->instance->GetInstanceId());\ if (!MapEventBindings->HasBindingsFor(mapKey) && !InstanceEventBindings->HasBindingsFor(instanceKey))\ return;\ - LOCK_ALE;\ + LOCK_ALE_STATE;\ PushInstanceData(L, AI);\ Push(AI->instance) @@ -32,7 +32,7 @@ using namespace Hooks; auto instanceKey = EntryKey(EVENT, AI->instance->GetInstanceId());\ if (!MapEventBindings->HasBindingsFor(mapKey) && !InstanceEventBindings->HasBindingsFor(instanceKey))\ return RETVAL;\ - LOCK_ALE;\ + LOCK_ALE_STATE;\ PushInstanceData(L, AI);\ Push(AI->instance) diff --git a/src/LuaEngine/hooks/ItemHooks.cpp b/src/LuaEngine/hooks/ItemHooks.cpp index 9bc347480c..93afe065e9 100644 --- a/src/LuaEngine/hooks/ItemHooks.cpp +++ b/src/LuaEngine/hooks/ItemHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!ItemEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!ItemEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, Item* pTarget) { diff --git a/src/LuaEngine/hooks/PlayerHooks.cpp b/src/LuaEngine/hooks/PlayerHooks.cpp index 7649274840..abd7f1995d 100644 --- a/src/LuaEngine/hooks/PlayerHooks.cpp +++ b/src/LuaEngine/hooks/PlayerHooks.cpp @@ -13,7 +13,7 @@ using namespace Hooks; -#define START_HOOK(EVENT) \ +#define START_HOOK_WORLD(EVENT) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return;\ auto key = EventKey(EVENT);\ @@ -21,17 +21,33 @@ using namespace Hooks; return;\ LOCK_ALE -#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ +#define START_HOOK_WORLD_WITH_RETVAL(EVENT, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return RETVAL;\ auto key = EventKey(EVENT);\ if (!PlayerEventBindings->HasBindingsFor(key))\ return RETVAL;\ LOCK_ALE + +#define START_HOOK_MAP(EVENT) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return;\ + auto key = EventKey(EVENT);\ + if (!PlayerEventBindings->HasBindingsFor(key))\ + return;\ + LOCK_ALE_STATE + +#define START_HOOK_MAP_WITH_RETVAL(EVENT, RETVAL) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return RETVAL;\ + auto key = EventKey(EVENT);\ + if (!PlayerEventBindings->HasBindingsFor(key))\ + return RETVAL;\ + LOCK_ALE_STATE void ALE::OnLearnTalents(Player* pPlayer, uint32 talentId, uint32 talentRank, uint32 spellid) { - START_HOOK(PLAYER_EVENT_ON_LEARN_TALENTS); + START_HOOK_MAP(PLAYER_EVENT_ON_LEARN_TALENTS); Push(pPlayer); Push(talentId); Push(talentRank); @@ -54,7 +70,7 @@ bool ALE::OnCommand(ChatHandler& handler, const char* text) } } - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_COMMAND, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_COMMAND, true); Push(player); Push(text); Push(&handler); @@ -63,7 +79,7 @@ bool ALE::OnCommand(ChatHandler& handler, const char* text) void ALE::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, ObjectGuid guid) { - START_HOOK(PLAYER_EVENT_ON_LOOT_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_LOOT_ITEM); Push(pPlayer); Push(pItem); Push(count); @@ -73,7 +89,7 @@ void ALE::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, ObjectGuid guid void ALE::OnLootMoney(Player* pPlayer, uint32 amount) { - START_HOOK(PLAYER_EVENT_ON_LOOT_MONEY); + START_HOOK_MAP(PLAYER_EVENT_ON_LOOT_MONEY); Push(pPlayer); Push(amount); CallAllFunctions(PlayerEventBindings, key); @@ -81,28 +97,28 @@ void ALE::OnLootMoney(Player* pPlayer, uint32 amount) void ALE::OnFirstLogin(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_FIRST_LOGIN); + START_HOOK_WORLD(PLAYER_EVENT_ON_FIRST_LOGIN); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnRepop(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_REPOP); + START_HOOK_MAP(PLAYER_EVENT_ON_REPOP); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnResurrect(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_RESURRECT); + START_HOOK_MAP(PLAYER_EVENT_ON_RESURRECT); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnQuestAbandon(Player* pPlayer, uint32 questId) { - START_HOOK(PLAYER_EVENT_ON_QUEST_ABANDON); + START_HOOK_MAP(PLAYER_EVENT_ON_QUEST_ABANDON); Push(pPlayer); Push(questId); CallAllFunctions(PlayerEventBindings, key); @@ -110,7 +126,7 @@ void ALE::OnQuestAbandon(Player* pPlayer, uint32 questId) void ALE::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot) { - START_HOOK(PLAYER_EVENT_ON_EQUIP); + START_HOOK_MAP(PLAYER_EVENT_ON_EQUIP); Push(pPlayer); Push(pItem); Push(bag); @@ -120,7 +136,7 @@ void ALE::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot) InventoryResult ALE::OnCanUseItem(const Player* pPlayer, uint32 itemEntry) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_USE_ITEM, EQUIP_ERR_OK); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_USE_ITEM, EQUIP_ERR_OK); InventoryResult result = EQUIP_ERR_OK; Push(pPlayer); Push(itemEntry); @@ -141,7 +157,7 @@ InventoryResult ALE::OnCanUseItem(const Player* pPlayer, uint32 itemEntry) } void ALE::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy) { - START_HOOK(PLAYER_EVENT_ON_ENTER_COMBAT); + START_HOOK_MAP(PLAYER_EVENT_ON_ENTER_COMBAT); Push(pPlayer); Push(pEnemy); CallAllFunctions(PlayerEventBindings, key); @@ -149,14 +165,14 @@ void ALE::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy) void ALE::OnPlayerLeaveCombat(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_LEAVE_COMBAT); + START_HOOK_MAP(PLAYER_EVENT_ON_LEAVE_COMBAT); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnPVPKill(Player* pKiller, Player* pKilled) { - START_HOOK(PLAYER_EVENT_ON_KILL_PLAYER); + START_HOOK_MAP(PLAYER_EVENT_ON_KILL_PLAYER); Push(pKiller); Push(pKilled); CallAllFunctions(PlayerEventBindings, key); @@ -164,7 +180,7 @@ void ALE::OnPVPKill(Player* pKiller, Player* pKilled) void ALE::OnCreatureKill(Player* pKiller, Creature* pKilled) { - START_HOOK(PLAYER_EVENT_ON_KILL_CREATURE); + START_HOOK_MAP(PLAYER_EVENT_ON_KILL_CREATURE); Push(pKiller); Push(pKilled); CallAllFunctions(PlayerEventBindings, key); @@ -172,7 +188,7 @@ void ALE::OnCreatureKill(Player* pKiller, Creature* pKilled) void ALE::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled) { - START_HOOK(PLAYER_EVENT_ON_KILLED_BY_CREATURE); + START_HOOK_MAP(PLAYER_EVENT_ON_KILLED_BY_CREATURE); Push(pKiller); Push(pKilled); CallAllFunctions(PlayerEventBindings, key); @@ -180,7 +196,7 @@ void ALE::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled) void ALE::OnLevelChanged(Player* pPlayer, uint8 oldLevel) { - START_HOOK(PLAYER_EVENT_ON_LEVEL_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_LEVEL_CHANGE); Push(pPlayer); Push(oldLevel); CallAllFunctions(PlayerEventBindings, key); @@ -188,7 +204,7 @@ void ALE::OnLevelChanged(Player* pPlayer, uint8 oldLevel) void ALE::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints) { - START_HOOK(PLAYER_EVENT_ON_TALENTS_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_TALENTS_CHANGE); Push(pPlayer); Push(newPoints); CallAllFunctions(PlayerEventBindings, key); @@ -196,7 +212,7 @@ void ALE::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints) void ALE::OnTalentsReset(Player* pPlayer, bool noCost) { - START_HOOK(PLAYER_EVENT_ON_TALENTS_RESET); + START_HOOK_MAP(PLAYER_EVENT_ON_TALENTS_RESET); Push(pPlayer); Push(noCost); CallAllFunctions(PlayerEventBindings, key); @@ -204,7 +220,7 @@ void ALE::OnTalentsReset(Player* pPlayer, bool noCost) void ALE::OnMoneyChanged(Player* pPlayer, int32& amount) { - START_HOOK(PLAYER_EVENT_ON_MONEY_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_MONEY_CHANGE); Push(pPlayer); Push(amount); int amountIndex = lua_gettop(L); @@ -229,7 +245,7 @@ void ALE::OnMoneyChanged(Player* pPlayer, int32& amount) void ALE::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim, uint8 xpSource) { - START_HOOK(PLAYER_EVENT_ON_GIVE_XP); + START_HOOK_MAP(PLAYER_EVENT_ON_GIVE_XP); Push(pPlayer); Push(amount); Push(pVictim); @@ -256,7 +272,7 @@ void ALE::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim, uint8 xpSourc bool ALE::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_REPUTATION_CHANGE, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_REPUTATION_CHANGE, true); bool result = true; Push(pPlayer); Push(factionID); @@ -287,7 +303,7 @@ bool ALE::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, void ALE::OnDuelRequest(Player* pTarget, Player* pChallenger) { - START_HOOK(PLAYER_EVENT_ON_DUEL_REQUEST); + START_HOOK_MAP(PLAYER_EVENT_ON_DUEL_REQUEST); Push(pTarget); Push(pChallenger); CallAllFunctions(PlayerEventBindings, key); @@ -295,7 +311,7 @@ void ALE::OnDuelRequest(Player* pTarget, Player* pChallenger) void ALE::OnDuelStart(Player* pStarter, Player* pChallenger) { - START_HOOK(PLAYER_EVENT_ON_DUEL_START); + START_HOOK_MAP(PLAYER_EVENT_ON_DUEL_START); Push(pStarter); Push(pChallenger); CallAllFunctions(PlayerEventBindings, key); @@ -303,7 +319,7 @@ void ALE::OnDuelStart(Player* pStarter, Player* pChallenger) void ALE::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type) { - START_HOOK(PLAYER_EVENT_ON_DUEL_END); + START_HOOK_MAP(PLAYER_EVENT_ON_DUEL_END); Push(pWinner); Push(pLoser); Push(type); @@ -312,7 +328,7 @@ void ALE::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type) void ALE::OnEmote(Player* pPlayer, uint32 emote) { - START_HOOK(PLAYER_EVENT_ON_EMOTE); + START_HOOK_MAP(PLAYER_EVENT_ON_EMOTE); Push(pPlayer); Push(emote); CallAllFunctions(PlayerEventBindings, key); @@ -320,7 +336,7 @@ void ALE::OnEmote(Player* pPlayer, uint32 emote) void ALE::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) { - START_HOOK(PLAYER_EVENT_ON_TEXT_EMOTE); + START_HOOK_MAP(PLAYER_EVENT_ON_TEXT_EMOTE); Push(pPlayer); Push(textEmote); Push(emoteNum); @@ -330,7 +346,7 @@ void ALE::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, Object void ALE::OnPlayerSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck) { - START_HOOK(PLAYER_EVENT_ON_SPELL_CAST); + START_HOOK_MAP(PLAYER_EVENT_ON_SPELL_CAST); Push(pPlayer); Push(pSpell); Push(skipCheck); @@ -339,42 +355,42 @@ void ALE::OnPlayerSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck) void ALE::OnLogin(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_LOGIN); + START_HOOK_WORLD(PLAYER_EVENT_ON_LOGIN); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnLogout(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_LOGOUT); + START_HOOK_WORLD(PLAYER_EVENT_ON_LOGOUT); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnCreate(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_CHARACTER_CREATE); + START_HOOK_WORLD(PLAYER_EVENT_ON_CHARACTER_CREATE); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnDelete(uint32 guidlow) { - START_HOOK(PLAYER_EVENT_ON_CHARACTER_DELETE); + START_HOOK_WORLD(PLAYER_EVENT_ON_CHARACTER_DELETE); Push(guidlow); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnSave(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_SAVE); + START_HOOK_MAP(PLAYER_EVENT_ON_SAVE); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent) { - START_HOOK(PLAYER_EVENT_ON_BIND_TO_INSTANCE); + START_HOOK_MAP(PLAYER_EVENT_ON_BIND_TO_INSTANCE); Push(pPlayer); Push(difficulty); Push(mapid); @@ -384,7 +400,7 @@ void ALE::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, void ALE::OnUpdateArea(Player* pPlayer, uint32 oldArea, uint32 newArea) { - START_HOOK(PLAYER_EVENT_ON_UPDATE_AREA); + START_HOOK_MAP(PLAYER_EVENT_ON_UPDATE_AREA); Push(pPlayer); Push(oldArea); Push(newArea); @@ -393,7 +409,7 @@ void ALE::OnUpdateArea(Player* pPlayer, uint32 oldArea, uint32 newArea) void ALE::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea) { - START_HOOK(PLAYER_EVENT_ON_UPDATE_ZONE); + START_HOOK_MAP(PLAYER_EVENT_ON_UPDATE_ZONE); Push(pPlayer); Push(newZone); Push(newArea); @@ -402,7 +418,7 @@ void ALE::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea) void ALE::OnMapChanged(Player* player) { - START_HOOK(PLAYER_EVENT_ON_MAP_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_MAP_CHANGE); Push(player); CallAllFunctions(PlayerEventBindings, key); } @@ -412,7 +428,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg) if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -442,7 +458,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Gr if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, NULL, pGroup, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_GROUP_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_GROUP_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -473,7 +489,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Gu if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, pGuild, NULL, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_GUILD_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_GUILD_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -504,7 +520,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Ch if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, pChannel); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CHANNEL_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_CHANNEL_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -535,7 +551,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Pl if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_WHISPER, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_WHISPER, true); bool result = true; Push(pPlayer); Push(msg); @@ -563,7 +579,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Pl void ALE::OnPetAddedToWorld(Player* player, Creature* pet) { - START_HOOK(PLAYER_EVENT_ON_PET_ADDED_TO_WORLD); + START_HOOK_MAP(PLAYER_EVENT_ON_PET_ADDED_TO_WORLD); Push(player); Push(pet); CallAllFunctions(PlayerEventBindings, key); @@ -571,7 +587,7 @@ void ALE::OnPetAddedToWorld(Player* player, Creature* pet) void ALE::OnLearnSpell(Player* player, uint32 spellId) { - START_HOOK(PLAYER_EVENT_ON_LEARN_SPELL); + START_HOOK_MAP(PLAYER_EVENT_ON_LEARN_SPELL); Push(player); Push(spellId); CallAllFunctions(PlayerEventBindings, key); @@ -579,7 +595,7 @@ void ALE::OnLearnSpell(Player* player, uint32 spellId) void ALE::OnAchiComplete(Player* player, AchievementEntry const* achievement) { - START_HOOK(PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE); + START_HOOK_MAP(PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE); Push(player); Push(achievement); CallAllFunctions(PlayerEventBindings, key); @@ -587,7 +603,7 @@ void ALE::OnAchiComplete(Player* player, AchievementEntry const* achievement) void ALE::OnFfaPvpStateUpdate(Player* player, bool hasFfaPvp) { - START_HOOK(PLAYER_EVENT_ON_FFAPVP_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_FFAPVP_CHANGE); Push(player); Push(hasFfaPvp); CallAllFunctions(PlayerEventBindings, key); @@ -595,7 +611,7 @@ void ALE::OnFfaPvpStateUpdate(Player* player, bool hasFfaPvp) bool ALE::OnCanInitTrade(Player* player, Player* target) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_INIT_TRADE, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_INIT_TRADE, true); Push(player); Push(target); return CallAllFunctionsBool(PlayerEventBindings, key); @@ -603,7 +619,7 @@ bool ALE::OnCanInitTrade(Player* player, Player* target) bool ALE::OnCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 cod, Item* item) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_SEND_MAIL, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_SEND_MAIL, true); Push(player); Push(receiverGuid); Push(mailbox); @@ -617,7 +633,7 @@ bool ALE::OnCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mail bool ALE::OnCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_JOIN_LFG, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_JOIN_LFG, true); Push(player); Push(roles); @@ -639,7 +655,7 @@ bool ALE::OnCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons void ALE::OnQuestRewardItem(Player* player, Item* item, uint32 count) { - START_HOOK(PLAYER_EVENT_ON_QUEST_REWARD_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_QUEST_REWARD_ITEM); Push(player); Push(item); Push(count); @@ -648,7 +664,7 @@ void ALE::OnQuestRewardItem(Player* player, Item* item, uint32 count) void ALE::OnCreateItem(Player* player, Item* item, uint32 count) { - START_HOOK(PLAYER_EVENT_ON_CREATE_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_CREATE_ITEM); Push(player); Push(item); Push(count); @@ -657,7 +673,7 @@ void ALE::OnCreateItem(Player* player, Item* item, uint32 count) void ALE::OnStoreNewItem(Player* player, Item* item, uint32 count) { - START_HOOK(PLAYER_EVENT_ON_STORE_NEW_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_STORE_NEW_ITEM); Push(player); Push(item); Push(count); @@ -666,7 +682,7 @@ void ALE::OnStoreNewItem(Player* player, Item* item, uint32 count) void ALE::OnPlayerCompleteQuest(Player* player, Quest const* quest) { - START_HOOK(PLAYER_EVENT_ON_COMPLETE_QUEST); + START_HOOK_MAP(PLAYER_EVENT_ON_COMPLETE_QUEST); Push(player); Push(quest); CallAllFunctions(PlayerEventBindings, key); @@ -674,7 +690,7 @@ void ALE::OnPlayerCompleteQuest(Player* player, Quest const* quest) bool ALE::OnCanGroupInvite(Player* player, std::string& memberName) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_GROUP_INVITE, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_GROUP_INVITE, true); Push(player); Push(memberName); return CallAllFunctionsBool(PlayerEventBindings, key); @@ -682,7 +698,7 @@ bool ALE::OnCanGroupInvite(Player* player, std::string& memberName) void ALE::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) { - START_HOOK(PLAYER_EVENT_ON_GROUP_ROLL_REWARD_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_GROUP_ROLL_REWARD_ITEM); Push(player); Push(item); Push(count); @@ -693,7 +709,7 @@ void ALE::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVo void ALE::OnBattlegroundDesertion(Player* player, const BattlegroundDesertionType type) { - START_HOOK(PLAYER_EVENT_ON_BG_DESERTION); + START_HOOK_MAP(PLAYER_EVENT_ON_BG_DESERTION); Push(player); Push(type); CallAllFunctions(PlayerEventBindings, key); @@ -701,7 +717,7 @@ void ALE::OnBattlegroundDesertion(Player* player, const BattlegroundDesertionTyp void ALE::OnCreatureKilledByPet(Player* player, Creature* killed) { - START_HOOK(PLAYER_EVENT_ON_PET_KILL); + START_HOOK_MAP(PLAYER_EVENT_ON_PET_KILL); Push(player); Push(killed); CallAllFunctions(PlayerEventBindings, key); @@ -709,7 +725,7 @@ void ALE::OnCreatureKilledByPet(Player* player, Creature* killed) bool ALE::OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_UPDATE_SKILL, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_UPDATE_SKILL, true); Push(player); Push(skill_id); return CallAllFunctionsBool(PlayerEventBindings, key); @@ -717,7 +733,7 @@ bool ALE::OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) void ALE::OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step) { - START_HOOK(PLAYER_EVENT_ON_BEFORE_UPDATE_SKILL); + START_HOOK_MAP(PLAYER_EVENT_ON_BEFORE_UPDATE_SKILL); Push(player); Push(skill_id); Push(value); @@ -744,7 +760,7 @@ void ALE::OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& val void ALE::OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uint32 max, uint32 step, uint32 new_value) { - START_HOOK(PLAYER_EVENT_ON_UPDATE_SKILL); + START_HOOK_MAP(PLAYER_EVENT_ON_UPDATE_SKILL); Push(player); Push(skill_id); Push(value); @@ -756,21 +772,21 @@ void ALE::OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uin bool ALE::CanPlayerResurrect(Player* player) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_RESURRECT, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_RESURRECT, true); Push(player); return CallAllFunctionsBool(PlayerEventBindings, key); } void ALE::OnPlayerReleasedGhost(Player* player) { - START_HOOK(PLAYER_EVENT_ON_RELEASED_GHOST); + START_HOOK_MAP(PLAYER_EVENT_ON_RELEASED_GHOST); Push(player); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnPlayerQuestAccept(Player* player, Quest const* quest) { - START_HOOK(PLAYER_EVENT_ON_QUEST_ACCEPT); + START_HOOK_MAP(PLAYER_EVENT_ON_QUEST_ACCEPT); Push(player); Push(quest); CallAllFunctions(PlayerEventBindings, key); @@ -778,7 +794,7 @@ void ALE::OnPlayerQuestAccept(Player* player, Quest const* quest) void ALE::OnPlayerAuraApply(Player* player, Aura* aura) { - START_HOOK(PLAYER_EVENT_ON_AURA_APPLY); + START_HOOK_MAP(PLAYER_EVENT_ON_AURA_APPLY); Push(player); Push(aura); CallAllFunctions(PlayerEventBindings, key); @@ -786,7 +802,7 @@ void ALE::OnPlayerAuraApply(Player* player, Aura* aura) void ALE::OnPlayerHeal(Player* player, Unit* target, uint32& gain) { - START_HOOK(PLAYER_EVENT_ON_HEAL); + START_HOOK_MAP(PLAYER_EVENT_ON_HEAL); Push(player); Push(target); Push(gain); @@ -811,7 +827,7 @@ void ALE::OnPlayerHeal(Player* player, Unit* target, uint32& gain) void ALE::OnPlayerDamage(Player* player, Unit* target, uint32& damage) { - START_HOOK(PLAYER_EVENT_ON_DAMAGE); + START_HOOK_MAP(PLAYER_EVENT_ON_DAMAGE); Push(player); Push(target); Push(damage); @@ -836,7 +852,7 @@ void ALE::OnPlayerDamage(Player* player, Unit* target, uint32& damage) void ALE::OnPlayerAuraRemove(Player* player, Aura* aura, AuraRemoveMode mode) { - START_HOOK(PLAYER_EVENT_ON_AURA_REMOVE); + START_HOOK_MAP(PLAYER_EVENT_ON_AURA_REMOVE); Push(player); Push(aura); Push(mode); @@ -845,7 +861,7 @@ void ALE::OnPlayerAuraRemove(Player* player, Aura* aura, AuraRemoveMode mode) void ALE::OnPlayerModifyPeriodicDamageAurasTick(Player* player, Unit* target, uint32& damage, SpellInfo const* spellInfo) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK); Push(player); Push(target); Push(damage); @@ -871,7 +887,7 @@ void ALE::OnPlayerModifyPeriodicDamageAurasTick(Player* player, Unit* target, ui void ALE::OnPlayerModifyMeleeDamage(Player* player, Unit* target, uint32& damage) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_MELEE_DAMAGE); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_MELEE_DAMAGE); Push(player); Push(target); Push(damage); @@ -896,7 +912,7 @@ void ALE::OnPlayerModifyMeleeDamage(Player* player, Unit* target, uint32& damage void ALE::OnPlayerModifySpellDamageTaken(Player* player, Unit* target, int32& damage, SpellInfo const* spellInfo) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN); Push(player); Push(target); Push(damage); @@ -922,7 +938,7 @@ void ALE::OnPlayerModifySpellDamageTaken(Player* player, Unit* target, int32& da void ALE::OnPlayerModifyHealReceived(Player* player, Unit* target, uint32& heal, SpellInfo const* spellInfo) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_HEAL_RECEIVED); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_HEAL_RECEIVED); Push(player); Push(target); Push(heal); @@ -948,7 +964,7 @@ void ALE::OnPlayerModifyHealReceived(Player* player, Unit* target, uint32& heal, uint32 ALE::OnPlayerDealDamage(Player* player, Unit* target, uint32 damage, DamageEffectType damagetype) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_DEAL_DAMAGE, damage); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_DEAL_DAMAGE, damage); Push(player); Push(target); Push(damage); diff --git a/src/LuaEngine/hooks/ServerHooks.cpp b/src/LuaEngine/hooks/ServerHooks.cpp index f305c97b7e..2dd7f4daf0 100644 --- a/src/LuaEngine/hooks/ServerHooks.cpp +++ b/src/LuaEngine/hooks/ServerHooks.cpp @@ -14,7 +14,7 @@ using namespace Hooks; -#define START_HOOK(EVENT) \ +#define START_HOOK_WORLD(EVENT) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return;\ auto key = EventKey(EVENT);\ @@ -22,7 +22,7 @@ using namespace Hooks; return;\ LOCK_ALE -#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ +#define START_HOOK_WORLD_WITH_RETVAL(EVENT, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return RETVAL;\ auto key = EventKey(EVENT);\ @@ -30,9 +30,25 @@ using namespace Hooks; return RETVAL;\ LOCK_ALE +#define START_HOOK_MAP(EVENT) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return;\ + auto key = EventKey(EVENT);\ + if (!ServerEventBindings->HasBindingsFor(key))\ + return;\ + LOCK_ALE_STATE + +#define START_HOOK_MAP_WITH_RETVAL(EVENT, RETVAL) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return RETVAL;\ + auto key = EventKey(EVENT);\ + if (!ServerEventBindings->HasBindingsFor(key))\ + return RETVAL;\ + LOCK_ALE_STATE + bool ALE::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* receiver, Guild* guild, Group* group, Channel* channel) { - START_HOOK_WITH_RETVAL(ADDON_EVENT_ON_MESSAGE, true); + START_HOOK_WORLD_WITH_RETVAL(ADDON_EVENT_ON_MESSAGE, true); Push(sender); Push(type); @@ -66,7 +82,7 @@ bool ALE::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* void ALE::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* obj) { - LOCK_ALE; + LOCK_ALE_STATE; ASSERT(!event_level); // Get function @@ -87,34 +103,34 @@ void ALE::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* obj void ALE::OnGameEventStart(uint32 eventid) { - START_HOOK(GAME_EVENT_START); + START_HOOK_WORLD(GAME_EVENT_START); Push(eventid); CallAllFunctions(ServerEventBindings, key); } void ALE::OnGameEventStop(uint32 eventid) { - START_HOOK(GAME_EVENT_STOP); + START_HOOK_WORLD(GAME_EVENT_STOP); Push(eventid); CallAllFunctions(ServerEventBindings, key); } void ALE::OnLuaStateClose() { - START_HOOK(ALE_EVENT_ON_LUA_STATE_CLOSE); + START_HOOK_MAP(ALE_EVENT_ON_LUA_STATE_CLOSE); // Uses map since each state, including world (-1), calls this on close CallAllFunctions(ServerEventBindings, key); } void ALE::OnLuaStateOpen() { - START_HOOK(ALE_EVENT_ON_LUA_STATE_OPEN); + START_HOOK_MAP(ALE_EVENT_ON_LUA_STATE_OPEN); // Uses map since each state, including world (-1), calls this on open CallAllFunctions(ServerEventBindings, key); } // AreaTrigger bool ALE::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger) { - START_HOOK_WITH_RETVAL(TRIGGER_EVENT_ON_TRIGGER, false); + START_HOOK_MAP_WITH_RETVAL(TRIGGER_EVENT_ON_TRIGGER, false); Push(pPlayer); Push(pTrigger->entry); @@ -124,7 +140,7 @@ bool ALE::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger) // Weather void ALE::OnChange(Weather* /*weather*/, uint32 zone, WeatherState state, float grade) { - START_HOOK(WEATHER_EVENT_ON_CHANGE); + START_HOOK_WORLD(WEATHER_EVENT_ON_CHANGE); Push(zone); Push(state); Push(grade); @@ -142,7 +158,7 @@ void ALE::OnAdd(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_ADD); + START_HOOK_WORLD(AUCTION_EVENT_ON_ADD); Push(entry->Id); Push(owner); Push(item); @@ -164,7 +180,7 @@ void ALE::OnRemove(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_REMOVE); + START_HOOK_WORLD(AUCTION_EVENT_ON_REMOVE); Push(entry->Id); Push(owner); Push(item); @@ -186,7 +202,7 @@ void ALE::OnSuccessful(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_SUCCESSFUL); + START_HOOK_WORLD(AUCTION_EVENT_ON_SUCCESSFUL); Push(entry->Id); Push(owner); Push(item); @@ -208,7 +224,7 @@ void ALE::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_EXPIRE); + START_HOOK_WORLD(AUCTION_EVENT_ON_EXPIRE); Push(entry->Id); Push(owner); Push(item); @@ -222,14 +238,14 @@ void ALE::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry) void ALE::OnOpenStateChange(bool open) { - START_HOOK(WORLD_EVENT_ON_OPEN_STATE_CHANGE); + START_HOOK_WORLD(WORLD_EVENT_ON_OPEN_STATE_CHANGE); Push(open); CallAllFunctions(ServerEventBindings, key); } void ALE::OnConfigLoad(bool reload, bool isBefore) { - START_HOOK(WORLD_EVENT_ON_CONFIG_LOAD); + START_HOOK_WORLD(WORLD_EVENT_ON_CONFIG_LOAD); Push(reload); Push(isBefore); CallAllFunctions(ServerEventBindings, key); @@ -237,7 +253,7 @@ void ALE::OnConfigLoad(bool reload, bool isBefore) void ALE::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask) { - START_HOOK(WORLD_EVENT_ON_SHUTDOWN_INIT); + START_HOOK_WORLD(WORLD_EVENT_ON_SHUTDOWN_INIT); Push(code); Push(mask); CallAllFunctions(ServerEventBindings, key); @@ -245,7 +261,7 @@ void ALE::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask) void ALE::OnShutdownCancel() { - START_HOOK(WORLD_EVENT_ON_SHUTDOWN_CANCEL); + START_HOOK_WORLD(WORLD_EVENT_ON_SHUTDOWN_CANCEL); CallAllFunctions(ServerEventBindings, key); } @@ -261,41 +277,53 @@ void ALE::OnWorldUpdate(uint32 diff) httpManager.HandleHttpResponses(); queryProcessor.ProcessReadyCallbacks(); - START_HOOK(WORLD_EVENT_ON_UPDATE); + { + std::shared_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + { + if (state) + { + state->httpManager.HandleHttpResponses(); + state->queryProcessor.ProcessReadyCallbacks(); + } + } + } + + START_HOOK_WORLD(WORLD_EVENT_ON_UPDATE); Push(diff); CallAllFunctions(ServerEventBindings, key); } void ALE::OnStartup() { - START_HOOK(WORLD_EVENT_ON_STARTUP); + START_HOOK_WORLD(WORLD_EVENT_ON_STARTUP); CallAllFunctions(ServerEventBindings, key); } void ALE::OnShutdown() { - START_HOOK(WORLD_EVENT_ON_SHUTDOWN); + START_HOOK_WORLD(WORLD_EVENT_ON_SHUTDOWN); CallAllFunctions(ServerEventBindings, key); } /* Map */ void ALE::OnCreate(Map* map) { - START_HOOK(MAP_EVENT_ON_CREATE); + START_HOOK_MAP(MAP_EVENT_ON_CREATE); Push(map); CallAllFunctions(ServerEventBindings, key); } void ALE::OnDestroy(Map* map) { - START_HOOK(MAP_EVENT_ON_DESTROY); + START_HOOK_MAP(MAP_EVENT_ON_DESTROY); Push(map); CallAllFunctions(ServerEventBindings, key); } void ALE::OnPlayerEnter(Map* map, Player* player) { - START_HOOK(MAP_EVENT_ON_PLAYER_ENTER); + START_HOOK_MAP(MAP_EVENT_ON_PLAYER_ENTER); Push(map); Push(player); CallAllFunctions(ServerEventBindings, key); @@ -303,7 +331,7 @@ void ALE::OnPlayerEnter(Map* map, Player* player) void ALE::OnPlayerLeave(Map* map, Player* player) { - START_HOOK(MAP_EVENT_ON_PLAYER_LEAVE); + START_HOOK_MAP(MAP_EVENT_ON_PLAYER_LEAVE); Push(map); Push(player); CallAllFunctions(ServerEventBindings, key); @@ -311,9 +339,9 @@ void ALE::OnPlayerLeave(Map* map, Player* player) void ALE::OnUpdate(Map* map, uint32 diff) { - START_HOOK(MAP_EVENT_ON_UPDATE); - // enable this for multithread - // eventMgr->globalProcessor->Update(diff); + eventMgr->globalProcessor->Update(diff); + + START_HOOK_MAP(MAP_EVENT_ON_UPDATE); Push(map); Push(diff); CallAllFunctions(ServerEventBindings, key); @@ -321,14 +349,14 @@ void ALE::OnUpdate(Map* map, uint32 diff) void ALE::OnRemove(GameObject* gameobject) { - START_HOOK(WORLD_EVENT_ON_DELETE_GAMEOBJECT); + START_HOOK_MAP(WORLD_EVENT_ON_DELETE_GAMEOBJECT); Push(gameobject); CallAllFunctions(ServerEventBindings, key); } void ALE::OnRemove(Creature* creature) { - START_HOOK(WORLD_EVENT_ON_DELETE_CREATURE); + START_HOOK_MAP(WORLD_EVENT_ON_DELETE_CREATURE); Push(creature); CallAllFunctions(ServerEventBindings, key); } diff --git a/src/LuaEngine/hooks/SpellHooks.cpp b/src/LuaEngine/hooks/SpellHooks.cpp index 8c0801893e..0016757bba 100644 --- a/src/LuaEngine/hooks/SpellHooks.cpp +++ b/src/LuaEngine/hooks/SpellHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!SpellEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!SpellEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnSpellCastCancel(Unit* caster, Spell* spell, SpellInfo const* spellInfo, bool bySelf) { diff --git a/src/LuaEngine/hooks/VehicleHooks.cpp b/src/LuaEngine/hooks/VehicleHooks.cpp index f03a9657f9..b1319d27bf 100644 --- a/src/LuaEngine/hooks/VehicleHooks.cpp +++ b/src/LuaEngine/hooks/VehicleHooks.cpp @@ -18,7 +18,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!VehicleEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnInstall(Vehicle* vehicle) { diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index cebb7bc6d6..f92ee700aa 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -146,8 +146,16 @@ namespace LuaGlobalFunctions */ int GetStateMap(lua_State* L) { - // Until AC supports multistate, this will always return nil - ALE::Push(L); + ALE* E = ALE::GetALE(L); + if (E->GetStateMapId() == ALE_GLOBAL_STATE) + { + ALE::Push(L); + return 1; + } + + // Get the map object and push it + Map* map = sMapMgr->FindMap(E->GetStateMapId(), 0); + ALE::Push(L, map); return 1; } @@ -158,8 +166,13 @@ namespace LuaGlobalFunctions */ int GetStateMapId(lua_State* L) { - // Until AC supports multistate, this will always return -1 - ALE::Push(L, -1); + ALE* E = ALE::GetALE(L); + if (E->GetStateMapId() == ALE_GLOBAL_STATE) + { + ALE::Push(L, -1); + return 1; + } + ALE::Push(L, (int32)E->GetStateMapId()); return 1; } @@ -170,8 +183,8 @@ namespace LuaGlobalFunctions */ int GetStateInstanceId(lua_State* L) { - // Until AC supports multistate, this will always return 0 - ALE::Push(L, 0); + ALE* E = ALE::GetALE(L); + ALE::Push(L, E->GetStateInstanceId()); return 1; } @@ -1445,7 +1458,9 @@ namespace LuaGlobalFunctions return 0; } - ALE::GALE->queryProcessor.AddCallback(db.AsyncQuery(query).WithCallback([L, funcRef](QueryResult result) + ALE* sALE = ALE::GetALE(L); + + sALE->queryProcessor.AddCallback(db.AsyncQuery(query).WithCallback([L, funcRef, sALE](QueryResult result) { ALEQuery* eq = result ? new ALEQuery(result) : nullptr; @@ -1458,7 +1473,7 @@ namespace LuaGlobalFunctions ALE::Push(L, eq); // Call function - ALE::GALE->ExecuteCall(1, 0); + sALE->ExecuteCall(1, 0); luaL_unref(L, LUA_REGISTRYINDEX, funcRef); })); @@ -1732,7 +1747,8 @@ namespace LuaGlobalFunctions int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) { - ALE::GetALE(L)->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats); + ALE* callingE = ALE::GetALE(L); + callingE->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats, callingE->GetSelfPtr()); ALE::Push(L, functionRef); } return 1; @@ -2699,7 +2715,8 @@ namespace LuaGlobalFunctions int funcRef = luaL_ref(L, LUA_REGISTRYINDEX); if (funcRef >= 0) { - ALE::GALE->httpManager.PushRequest(new HttpWorkItem(funcRef, httpVerb, url, body, bodyContentType, headers)); + ALE* sALE = ALE::GetALE(L); + sALE->httpManager.PushRequest(new HttpWorkItem(funcRef, sALE, httpVerb, url, body, bodyContentType, headers)); } else { diff --git a/src/LuaEngine/methods/WorldObjectMethods.h b/src/LuaEngine/methods/WorldObjectMethods.h index a92a435b01..7595c62bad 100644 --- a/src/LuaEngine/methods/WorldObjectMethods.h +++ b/src/LuaEngine/methods/WorldObjectMethods.h @@ -780,7 +780,9 @@ namespace LuaWorldObject int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) { - obj->ALEEvents->AddEvent(functionRef, min, max, repeats); + ALE* callingE = ALE::GetALE(L); + ALE** stateSlot = callingE->GetSelfPtr(); + obj->ALEEvents->AddEvent(functionRef, min, max, repeats, stateSlot); ALE::Push(L, functionRef); } return 1;