diff --git a/ElunaBinding.h b/ElunaBinding.h index d200967..deccccf 100644 --- a/ElunaBinding.h +++ b/ElunaBinding.h @@ -25,15 +25,23 @@ public: int functionReference; bool isTemporary; uint32 remainingShots; + Eluna& E; - Binding(int funcRef, uint32 shots) : + Binding(Eluna& _E, int funcRef, uint32 shots) : functionReference(funcRef), isTemporary(shots != 0), - remainingShots(shots) + remainingShots(shots), + E(_E) { } + + // Remove our function from the registry when the Binding is deleted. + ~Binding() + { + luaL_unref(E.L, LUA_REGISTRYINDEX, functionReference); + } }; - typedef std::vector FunctionRefVector; + typedef std::vector FunctionRefVector; typedef UNORDERED_MAP EventToFunctionsMap; Eluna& E; @@ -66,27 +74,35 @@ public: for (EventToFunctionsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) { for (FunctionRefVector::iterator it = itr->second.begin(); it != itr->second.end(); ++it) - luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).functionReference); + delete *it; itr->second.clear(); } Bindings.clear(); } + void Clear(uint32 event_id) + { + for (FunctionRefVector::iterator itr = Bindings[event_id].begin(); itr != Bindings[event_id].end(); ++itr) + delete *itr; + Bindings[event_id].clear(); + } + // Pushes the function references and updates the counters on the binds and erases them if the counter would reach 0 void PushFuncRefs(lua_State* L, int event_id) { for (FunctionRefVector::iterator it = Bindings[event_id].begin(); it != Bindings[event_id].end();) { FunctionRefVector::iterator it_old = it++; + Binding* binding = (*it_old); - lua_rawgeti(L, LUA_REGISTRYINDEX, (it_old->functionReference)); + lua_rawgeti(L, LUA_REGISTRYINDEX, binding->functionReference); - if (it_old->isTemporary) + if (binding->isTemporary) { - --it_old->remainingShots; - if (it_old->remainingShots == 0) + binding->remainingShots--; + if (binding->remainingShots == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, it_old->functionReference); + delete binding; Bindings[event_id].erase(it_old); } } @@ -98,7 +114,7 @@ public: void Insert(int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - Bindings[eventId].push_back(Binding(funcRef, shots)); + Bindings[eventId].push_back(new Binding(E, funcRef, shots)); } // Checks if there are events for ID @@ -132,7 +148,7 @@ public: for (EventToFunctionsMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) { for (FunctionRefVector::iterator i = it->second.begin(); i != it->second.end(); ++i) - luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).functionReference); + delete *i; it->second.clear(); } itr->second.clear(); @@ -140,21 +156,29 @@ public: Bindings.clear(); } + void Clear(uint32 entry, uint32 event_id) + { + for (FunctionRefVector::iterator itr = Bindings[entry][event_id].begin(); itr != Bindings[entry][event_id].end(); ++itr) + delete *itr; + Bindings[entry][event_id].clear(); + } + // Pushes the function references and updates the counters on the binds and erases them if the counter would reach 0 void PushFuncRefs(lua_State* L, int event_id, uint32 entry) { for (FunctionRefVector::iterator it = Bindings[entry][event_id].begin(); it != Bindings[entry][event_id].end();) { FunctionRefVector::iterator it_old = it++; + Binding* binding = (*it_old); - lua_rawgeti(L, LUA_REGISTRYINDEX, (it_old->functionReference)); + lua_rawgeti(L, LUA_REGISTRYINDEX, binding->functionReference); - if (it_old->isTemporary) + if (binding->isTemporary) { - --it_old->remainingShots; - if (it_old->remainingShots == 0) + binding->remainingShots--; + if (binding->remainingShots == 0) { - luaL_unref(L, LUA_REGISTRYINDEX, it_old->functionReference); + delete binding; Bindings[entry][event_id].erase(it_old); } } @@ -169,7 +193,7 @@ public: void Insert(uint32 entryId, int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - Bindings[entryId][eventId].push_back(Binding(funcRef, shots)); + Bindings[entryId][eventId].push_back(new Binding(E, funcRef, shots)); } // Returns true if the entry has registered binds diff --git a/GlobalMethods.h b/GlobalMethods.h index c328456..a50d942 100644 --- a/GlobalMethods.h +++ b/GlobalMethods.h @@ -7,6 +7,8 @@ #ifndef GLOBALMETHODS_H #define GLOBALMETHODS_H +#include "ElunaBinding.h" + namespace LuaGlobalFunctions { /** @@ -697,7 +699,7 @@ namespace LuaGlobalFunctions } /** - * Registers a [Battleground] event + * Registers a [BattleGround] event * *
      * enum BGEvents
@@ -710,7 +712,7 @@ namespace LuaGlobalFunctions
      * };
      * 
* - * @param uint32 event : [Battleground] event Id, refer to BGEvents above + * @param uint32 event : [BattleGround] event Id, refer to BGEvents above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" */ @@ -2347,5 +2349,177 @@ namespace LuaGlobalFunctions Eluna::Push(L, init); return 1; } + + /** + * Unbinds all event handlers for a particular [BattleGround] event. + * + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterBGEvent] + */ + int ClearBattleGroundEvents(Eluna* E, lua_State* L) + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + E->BGEventBindings->Clear(event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Creature] event/entry combination. + * + * @param uint32 entry : the ID of a [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureEvent] + */ + int ClearCreatureEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->CreatureEventBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Creature] gossip event/entry combination. + * + * @param uint32 entry : the ID of a [Creature] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterCreatureGossipEvent] + */ + int ClearCreatureGossipEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->CreatureGossipBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [GameObject] event/entry combination. + * + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectEvent] + */ + int ClearGameObjectEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->GameObjectEventBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [GameObject] gossip event/entry combination. + * + * @param uint32 entry : the ID of a [GameObject] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGameObjectGossipEvent] + */ + int ClearGameObjectGossipEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->GameObjectGossipBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Group] event. + * + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGroupEvent] + */ + int ClearGroupEvents(Eluna* E, lua_State* L) + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + E->GroupEventBindings->Clear(event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Guild] event. + * + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterGuildEvent] + */ + int ClearGuildEvents(Eluna* E, lua_State* L) + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + E->GuildEventBindings->Clear(event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Item] event/entry combination. + * + * @param uint32 entry : the ID of an [Item] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemEvent] + */ + int ClearItemEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->ItemEventBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Item] gossip event/entry combination. + * + * @param uint32 entry : the ID of a [] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterItemGossipEvent] + */ + int ClearItemGossipEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->ItemGossipBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Packet] event/entry combination. + * + * @param uint32 entry : the ID of a [Packet] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPacketEvent] + */ + int ClearPacketEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->PacketEventBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Player] event. + * + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerEvent] + */ + int ClearPlayerEvents(Eluna* E, lua_State* L) + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + E->PlayerEventBindings->Clear(event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular [Player] gossip event. + * + * @param uint32 entry : the ID of a [] whose handlers will be cleared + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterPlayerGossipEvent] + */ + int ClearPlayerGossipEvents(Eluna* E, lua_State* L) + { + uint32 entry = Eluna::CHECKVAL(L, 1); + uint32 event_type = Eluna::CHECKVAL(L, 2); + E->playerGossipBindings->Clear(entry, event_type); + return 0; + } + + /** + * Unbinds all event handlers for a particular server event. + * + * @param uint32 event_type : the event whose handlers will be cleared, see [Global:RegisterServerEvent] + */ + int ClearServerEvents(Eluna* E, lua_State* L) + { + uint32 event_type = Eluna::CHECKVAL(L, 1); + E->ServerEventBindings->Clear(event_type); + return 0; + } } #endif diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index 8f958a4..ccfef8d 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -55,6 +55,20 @@ ElunaGlobal::ElunaRegister GlobalMethods[] = { "RegisterPlayerGossipEvent", &LuaGlobalFunctions::RegisterPlayerGossipEvent }, // RegisterPlayerGossipEvent(menu_id, event, function) { "RegisterBGEvent", &LuaGlobalFunctions::RegisterBGEvent }, // RegisterBGEvent(event, function) + { "ClearBattleGroundEvents", &LuaGlobalFunctions::ClearBattleGroundEvents }, + { "ClearCreatureEvents", &LuaGlobalFunctions::ClearCreatureEvents }, + { "ClearCreatureGossipEvents", &LuaGlobalFunctions::ClearCreatureGossipEvents }, + { "ClearGameObjectEvents", &LuaGlobalFunctions::ClearGameObjectEvents }, + { "ClearGameObjectGossipEvents", &LuaGlobalFunctions::ClearGameObjectGossipEvents }, + { "ClearGroupEvents", &LuaGlobalFunctions::ClearGroupEvents }, + { "ClearGuildEvents", &LuaGlobalFunctions::ClearGuildEvents }, + { "ClearItemEvents", &LuaGlobalFunctions::ClearItemEvents }, + { "ClearItemGossipEvents", &LuaGlobalFunctions::ClearItemGossipEvents }, + { "ClearPacketEvents", &LuaGlobalFunctions::ClearPacketEvents }, + { "ClearPlayerEvents", &LuaGlobalFunctions::ClearPlayerEvents }, + { "ClearPlayerGossipEvents", &LuaGlobalFunctions::ClearPlayerGossipEvents }, + { "ClearServerEvents", &LuaGlobalFunctions::ClearServerEvents }, + // Getters { "GetLuaEngine", &LuaGlobalFunctions::GetLuaEngine }, { "GetCoreName", &LuaGlobalFunctions::GetCoreName },