diff --git a/ElunaBinding.h b/ElunaBinding.h index c0eafdb..ba53fb1 100644 --- a/ElunaBinding.h +++ b/ElunaBinding.h @@ -20,6 +20,10 @@ extern "C" class ElunaBind { public: + typedef std::pair FunctionRefCounterPair; // (function reference, remaining calls counter) + typedef std::vector FunctionRefVector; + typedef UNORDERED_MAP EventToFunctionsMap; + Eluna& E; const char* groupName; @@ -34,15 +38,15 @@ public: // unregisters all registered functions and clears all registered events from the bindings virtual void Clear() { }; + + // Updates the counters on all temporary bindings and erases them if the counter would reach 0. + virtual void UpdateTemporaryBindings() { }; }; template class EventBind : public ElunaBind { public: - typedef std::vector ElunaBindingMap; - typedef std::map ElunaEntryMap; - EventBind(const char* bindGroupName, Eluna& _E) : ElunaBind(bindGroupName, _E) { } @@ -50,30 +54,55 @@ public: // unregisters all registered functions and clears all registered events from the bind std::maps (reset) void Clear() override { - for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) + for (EventToFunctionsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) { - for (ElunaBindingMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) - luaL_unref(E.L, LUA_REGISTRYINDEX, (*it)); + for (FunctionRefVector::iterator it = itr->second.begin(); it != itr->second.end(); ++it) + luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).first); itr->second.clear(); } Bindings.clear(); } - void Insert(int eventId, int funcRef) // Inserts a new registered event + void UpdateTemporaryBindings() override { - Bindings[eventId].push_back(funcRef); + for (EventToFunctionsMap::iterator itr = Bindings.begin(); itr != Bindings.end();) + { + for (FunctionRefVector::iterator it = itr->second.begin(); it != itr->second.end();) + { + uint32 counter = (*it).second; + + if (counter > 1) + { + counter--; + (*it).second = counter; + it++; + } + else if (counter == 1) + { + luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).first); + it = itr->second.erase(it); + } + else + { + it++; + } + } + + // If there are no more entries in the vector, erase the vector. + if (itr->second.empty()) + { + itr = Bindings.erase(itr); + } + else + { + itr++; + } + } } - // Gets the binding std::map containing all registered events with the function refs for the entry - ElunaBindingMap* GetBindMap(T eventId) + void Insert(int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - if (Bindings.empty()) - return NULL; - ElunaEntryMap::iterator itr = Bindings.find(eventId); - if (itr == Bindings.end()) - return NULL; - - return &itr->second; + Bindings[eventId].push_back(std::make_pair(funcRef, shots)); } // Checks if there are events for ID @@ -86,16 +115,14 @@ public: return true; } - ElunaEntryMap Bindings; // Binding store Bindings[eventId] = {funcRef}; + EventToFunctionsMap Bindings; // Binding store Bindings[eventId] = {(funcRef, counter)}; }; template class EntryBind : public ElunaBind { public: - typedef std::vector FunctionRefVector; - typedef std::map ElunaBindingMap; - typedef UNORDERED_MAP ElunaEntryMap; + typedef UNORDERED_MAP EntryToEventsMap; EntryBind(const char* bindGroupName, Eluna& _E) : ElunaBind(bindGroupName, _E) { @@ -104,12 +131,12 @@ public: // unregisters all registered functions and clears all registered events from the bindmap void Clear() override { - for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) + for (EntryToEventsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr) { - for (ElunaBindingMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it) + 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)); + luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).first); it->second.clear(); } itr->second.clear(); @@ -117,21 +144,58 @@ public: Bindings.clear(); } - void Insert(uint32 entryId, int eventId, int funcRef) // Inserts a new registered event + void UpdateTemporaryBindings() override { - Bindings[entryId][eventId].push_back(funcRef); + for (EntryToEventsMap::iterator itr = Bindings.begin(); itr != Bindings.end();) + { + for (EventToFunctionsMap::iterator it = itr->second.begin(); it != itr->second.end();) + { + for (FunctionRefVector::iterator i = it->second.begin(); i != it->second.end();) + { + uint32 counter = (*i).second; + if (counter > 1) + { + counter--; + (*i).second = counter; + i++; + } + else if (counter == 1) + { + luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).first); + i = it->second.erase(i); + } + else + { + i++; + } + } + + // If there are no more entries in the vector, erase the vector. + if (it->second.empty()) + { + it = itr->second.erase(it); + } + else + { + it++; + } + } + + // If there are no more vector in the map, erase the map. + if (itr->second.empty()) + { + itr = Bindings.erase(itr); + } + else + { + itr++; + } + } } - // Gets the binding std::map containing all registered events with the function refs for the entry - const ElunaBindingMap* GetBindMap(uint32 entryId) const + void Insert(uint32 entryId, int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - if (Bindings.empty()) - return NULL; - ElunaEntryMap::const_iterator itr = Bindings.find(entryId); - if (itr == Bindings.end()) - return NULL; - - return &itr->second; + Bindings[entryId][eventId].push_back(std::make_pair(funcRef, shots)); } // Returns true if the entry has registered binds @@ -140,14 +204,22 @@ public: if (Bindings.empty()) return false; - ElunaEntryMap::const_iterator itr = Bindings.find(entryId); + EntryToEventsMap::const_iterator itr = Bindings.find(entryId); if (itr == Bindings.end()) return false; return itr->second.find(eventId) != itr->second.end(); } - ElunaEntryMap Bindings; // Binding store Bindings[entryId][eventId] = {funcRef}; + bool HasEvents(uint32 entryId) const + { + if (Bindings.empty()) + return false; + + return Bindings.find(entryId) != Bindings.end(); + } + + EntryToEventsMap Bindings; // Binding store Bindings[entryId][eventId] = {(funcRef, counter)}; }; #endif diff --git a/GlobalMethods.h b/GlobalMethods.h index 45faed8..b3b21e8 100644 --- a/GlobalMethods.h +++ b/GlobalMethods.h @@ -491,17 +491,30 @@ namespace LuaGlobalFunctions * * @param uint32 entry : opcode * @param uint32 event : packet event Id, refer to PacketEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterPacketEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_PACKET, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_PACKET, entry, ev, functionRef, shots); return 0; } @@ -566,16 +579,29 @@ namespace LuaGlobalFunctions * * * @param uint32 event : server event Id, refer to ServerEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterServerEvent(Eluna* E, lua_State* L) { uint32 ev = Eluna::CHECKVAL(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushvalue(L, 2); + uint32 shots; + + if (lua_isfunction(L, 2)) // If the second argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 2); + } + else // Otherwise, shots is the second argument and the function must be the third. + { + shots = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + lua_pushvalue(L, 3); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_SERVER, 0, ev, functionRef); + E->Register(HookMgr::REGTYPE_SERVER, 0, ev, functionRef, shots); return 0; } @@ -635,16 +661,29 @@ namespace LuaGlobalFunctions * * * @param uint32 event : [Player] event Id, refer to PlayerEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterPlayerEvent(Eluna* E, lua_State* L) { uint32 ev = Eluna::CHECKVAL(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushvalue(L, 2); + uint32 shots; + + if (lua_isfunction(L, 2)) // If the second argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 2); + } + else // Otherwise, shots is the second argument and the function must be the third. + { + shots = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + lua_pushvalue(L, 3); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_PLAYER, 0, ev, functionRef); + E->Register(HookMgr::REGTYPE_PLAYER, 0, ev, functionRef, shots); return 0; } @@ -672,16 +711,29 @@ namespace LuaGlobalFunctions * * * @param uint32 event : [Guild] event Id, refer to GuildEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterGuildEvent(Eluna* E, lua_State* L) { uint32 ev = Eluna::CHECKVAL(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushvalue(L, 2); + uint32 shots; + + if (lua_isfunction(L, 2)) // If the second argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 2); + } + else // Otherwise, shots is the second argument and the function must be the third. + { + shots = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + lua_pushvalue(L, 3); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_GUILD, 0, ev, functionRef); + E->Register(HookMgr::REGTYPE_GUILD, 0, ev, functionRef, shots); return 0; } @@ -704,16 +756,29 @@ namespace LuaGlobalFunctions * * * @param uint32 event : [Group] event Id, refer to GroupEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterGroupEvent(Eluna* E, lua_State* L) { uint32 ev = Eluna::CHECKVAL(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushvalue(L, 2); + uint32 shots; + + if (lua_isfunction(L, 2)) // If the second argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 2); + } + else // Otherwise, shots is the second argument and the function must be the third. + { + shots = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + lua_pushvalue(L, 3); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_GROUP, 0, ev, functionRef); + E->Register(HookMgr::REGTYPE_GROUP, 0, ev, functionRef, shots); return 0; } @@ -731,17 +796,30 @@ namespace LuaGlobalFunctions * * @param uint32 menu_id : [Creature] entry Id * @param uint32 event : [Creature] gossip event Id, refer to GossipEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterCreatureGossipEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_CREATURE_GOSSIP, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_CREATURE_GOSSIP, entry, ev, functionRef, shots); return 0; } @@ -759,17 +837,30 @@ namespace LuaGlobalFunctions * * @param uint32 menu_id : [GameObject] entry Id * @param uint32 event : [GameObject] gossip event Id, refer to GossipEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterGameObjectGossipEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_GAMEOBJECT_GOSSIP, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_GAMEOBJECT_GOSSIP, entry, ev, functionRef, shots); return 0; } @@ -790,17 +881,30 @@ namespace LuaGlobalFunctions * * @param uint32 entry : [Item] entry Id * @param uint32 event : [Item] event Id, refer to ItemEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterItemEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_ITEM, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_ITEM, entry, ev, functionRef, shots); return 0; } @@ -818,17 +922,30 @@ namespace LuaGlobalFunctions * * @param uint32 entry : [Item] entry Id * @param uint32 event : [Item] gossip event Id, refer to GossipEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterItemGossipEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_ITEM_GOSSIP, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_ITEM_GOSSIP, entry, ev, functionRef, shots); return 0; } @@ -846,17 +963,30 @@ namespace LuaGlobalFunctions * * @param uint32 menu_id : [Player] gossip menu Id * @param uint32 event : [Player] gossip event Id, refer to GossipEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterPlayerGossipEvent(Eluna* E, lua_State* L) { uint32 menu_id = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_PLAYER_GOSSIP, menu_id, ev, functionRef); + E->Register(HookMgr::REGTYPE_PLAYER_GOSSIP, menu_id, ev, functionRef, shots); return 0; } @@ -909,17 +1039,30 @@ namespace LuaGlobalFunctions * * @param uint32 entry : [Creature] entry Id * @param uint32 event : [Creature] event Id, refer to CreatureEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterCreatureEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_CREATURE, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_CREATURE, entry, ev, functionRef, shots); return 0; } @@ -948,17 +1091,30 @@ namespace LuaGlobalFunctions * * @param uint32 entry : [GameObject] entry Id * @param uint32 event : [GameObject] event Id, refer to GameObjectEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterGameObjectEvent(Eluna* E, lua_State* L) { uint32 entry = Eluna::CHECKVAL(L, 1); uint32 ev = Eluna::CHECKVAL(L, 2); - luaL_checktype(L, 3, LUA_TFUNCTION); - lua_pushvalue(L, 3); + uint32 shots; + + if (lua_isfunction(L, 3)) // If the third argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 3); + } + else // Otherwise, shots is the third argument and the function must be the fourth. + { + shots = Eluna::CHECKVAL(L, 3); + luaL_checktype(L, 4, LUA_TFUNCTION); + lua_pushvalue(L, 4); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_GAMEOBJECT, entry, ev, functionRef); + E->Register(HookMgr::REGTYPE_GAMEOBJECT, entry, ev, functionRef, shots); return 0; } @@ -977,16 +1133,29 @@ namespace LuaGlobalFunctions * * * @param uint32 event : [Battleground] event Id, refer to BGEvents above + * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @param function function : function to register */ int RegisterBGEvent(Eluna* E, lua_State* L) { uint32 ev = Eluna::CHECKVAL(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushvalue(L, 2); + uint32 shots; + + if (lua_isfunction(L, 2)) // If the second argument is a function, set shots to 0 for backwards-compatibility. + { + shots = 0; + lua_pushvalue(L, 2); + } + else // Otherwise, shots is the second argument and the function must be the third. + { + shots = Eluna::CHECKVAL(L, 2); + luaL_checktype(L, 3, LUA_TFUNCTION); + lua_pushvalue(L, 3); + } + int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef > 0) - E->Register(HookMgr::REGTYPE_BG, 0, ev, functionRef); + E->Register(HookMgr::REGTYPE_BG, 0, ev, functionRef, shots); return 0; } diff --git a/HookMgr.cpp b/HookMgr.cpp index ed5ae1c..292ab84 100644 --- a/HookMgr.cpp +++ b/HookMgr.cpp @@ -47,11 +47,12 @@ using namespace HookMgr; if (!BINDMAP->HasEvents(EVENT)) \ RET; \ lua_State* L = this->L; \ + ElunaBind* _LuaBind = this->BINDMAP; \ const char* _LuaBindType = this->BINDMAP->groupName; \ uint32 _LuaEvent = EVENT; \ int _LuaStackTop = lua_gettop(L); \ for (size_t i = 0; i < this->BINDMAP->Bindings[_LuaEvent].size(); ++i) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[_LuaEvent][i])); \ + lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[_LuaEvent][i].first)); \ int _LuaFuncTop = lua_gettop(L); \ int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \ Eluna::Push(L, _LuaEvent); @@ -81,11 +82,12 @@ using namespace HookMgr; if (!BINDMAP->HasEvents(ENTRY, EVENT)) \ RET; \ lua_State* L = this->L; \ - const char* _LuaBindType = this->BINDMAP->groupName; \ + ElunaBind* _LuaBind = this->BINDMAP; \ + const char* _LuaBindType = _LuaBind->groupName; \ uint32 _LuaEvent = EVENT; \ int _LuaStackTop = lua_gettop(L); \ for (size_t i = 0; i < this->BINDMAP->Bindings[ENTRY][_LuaEvent].size(); ++i) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i])); \ + lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].first)); \ int _LuaFuncTop = lua_gettop(L); \ int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \ Eluna::Push(L, _LuaEvent); @@ -121,6 +123,7 @@ using namespace HookMgr; ELUNA_LOG_ERROR("[Eluna]: Ending event %u for %s, stack top was %i and was supposed to be between %i and %i. Report to devs", _LuaEvent, _LuaBindType, lua_gettop(L), _LuaStackTop, _LuaStackTop + _LuaFuncCount * _LuaReturnValues); \ } \ lua_settop(L, _LuaStackTop); \ + _LuaBind->UpdateTemporaryBindings(); \ if (!this->event_level) \ this->InvalidateObjects(); // Invalidate objects on outermost hook call @@ -2204,7 +2207,7 @@ void Eluna::OnRemoveFromWorld(GameObject* gameobject) CreatureAI* Eluna::GetAI(Creature* creature) { - if (!CreatureEventBindings->GetBindMap(creature->GetEntry())) + if (!CreatureEventBindings->HasEvents(creature->GetEntry())) return NULL; return new ElunaCreatureAI(creature); } diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 1d6677d..ad5e26d 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -749,14 +749,14 @@ ElunaObject* Eluna::CHECKTYPE(lua_State* L, int narg, const char* tname, bool er } // Saves the function reference ID given to the register type's store for given entry under the given event -void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) +void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef, uint32 shots) { switch (regtype) { case HookMgr::REGTYPE_SERVER: if (evt < HookMgr::SERVER_EVENT_COUNT) { - ServerEventBindings->Insert(evt, functionRef); + ServerEventBindings->Insert(evt, functionRef, shots); return; } break; @@ -764,7 +764,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) case HookMgr::REGTYPE_PLAYER: if (evt < HookMgr::PLAYER_EVENT_COUNT) { - PlayerEventBindings->Insert(evt, functionRef); + PlayerEventBindings->Insert(evt, functionRef, shots); return; } break; @@ -772,7 +772,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) case HookMgr::REGTYPE_GUILD: if (evt < HookMgr::GUILD_EVENT_COUNT) { - GuildEventBindings->Insert(evt, functionRef); + GuildEventBindings->Insert(evt, functionRef, shots); return; } break; @@ -780,7 +780,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) case HookMgr::REGTYPE_GROUP: if (evt < HookMgr::GROUP_EVENT_COUNT) { - GroupEventBindings->Insert(evt, functionRef); + GroupEventBindings->Insert(evt, functionRef, shots); return; } break; @@ -788,7 +788,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) case HookMgr::REGTYPE_VEHICLE: if (evt < HookMgr::VEHICLE_EVENT_COUNT) { - VehicleEventBindings->Insert(evt, functionRef); + VehicleEventBindings->Insert(evt, functionRef, shots); return; } break; @@ -796,7 +796,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) case HookMgr::REGTYPE_BG: if (evt < HookMgr::BG_EVENT_COUNT) { - BGEventBindings->Insert(evt, functionRef); + BGEventBindings->Insert(evt, functionRef, shots); return; } break; @@ -811,7 +811,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - PacketEventBindings->Insert(id, evt, functionRef); + PacketEventBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -826,7 +826,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - CreatureEventBindings->Insert(id, evt, functionRef); + CreatureEventBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -841,7 +841,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - CreatureGossipBindings->Insert(id, evt, functionRef); + CreatureGossipBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -856,7 +856,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - GameObjectEventBindings->Insert(id, evt, functionRef); + GameObjectEventBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -871,7 +871,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - GameObjectGossipBindings->Insert(id, evt, functionRef); + GameObjectGossipBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -886,7 +886,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - ItemEventBindings->Insert(id, evt, functionRef); + ItemEventBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -901,7 +901,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) return; } - ItemGossipBindings->Insert(id, evt, functionRef); + ItemGossipBindings->Insert(id, evt, functionRef, shots); return; } break; @@ -909,7 +909,7 @@ void Eluna::Register(uint8 regtype, uint32 id, uint32 evt, int functionRef) case HookMgr::REGTYPE_PLAYER_GOSSIP: if (evt < HookMgr::GOSSIP_EVENT_COUNT) { - playerGossipBindings->Insert(id, evt, functionRef); + playerGossipBindings->Insert(id, evt, functionRef, shots); return; } break; diff --git a/LuaEngine.h b/LuaEngine.h index 85b9ae1..4cee8ba 100644 --- a/LuaEngine.h +++ b/LuaEngine.h @@ -154,7 +154,7 @@ public: static void report(lua_State*); void ExecuteCall(int params, int res); - void Register(uint8 reg, uint32 id, uint32 evt, int func); + void Register(uint8 reg, uint32 id, uint32 evt, int func, uint32 shots); void RunScripts(); void InvalidateObjects();