diff --git a/ElunaBinding.h b/ElunaBinding.h index ba53fb1..693afc2 100644 --- a/ElunaBinding.h +++ b/ElunaBinding.h @@ -20,8 +20,19 @@ extern "C" class ElunaBind { public: - typedef std::pair FunctionRefCounterPair; // (function reference, remaining calls counter) - typedef std::vector FunctionRefVector; + struct Binding + { + int functionReference; + bool isTemporary; + uint32 remainingShots; + + Binding(int funcRef, uint32 shots) : + functionReference(funcRef), + isTemporary(shots != 0), + remainingShots(shots) + {} + }; + typedef std::vector FunctionRefVector; typedef UNORDERED_MAP EventToFunctionsMap; Eluna& E; @@ -57,7 +68,7 @@ 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).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).functionReference); itr->second.clear(); } Bindings.clear(); @@ -69,17 +80,10 @@ public: { for (FunctionRefVector::iterator it = itr->second.begin(); it != itr->second.end();) { - uint32 counter = (*it).second; - - if (counter > 1) + Binding &b = (*it); + if (b.isTemporary && b.remainingShots == 0) { - counter--; - (*it).second = counter; - it++; - } - else if (counter == 1) - { - luaL_unref(E.L, LUA_REGISTRYINDEX, (*it).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, b.functionReference); it = itr->second.erase(it); } else @@ -102,7 +106,7 @@ public: void Insert(int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - Bindings[eventId].push_back(std::make_pair(funcRef, shots)); + Bindings[eventId].push_back(Binding(funcRef, shots)); } // Checks if there are events for ID @@ -136,7 +140,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).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).functionReference); it->second.clear(); } itr->second.clear(); @@ -152,16 +156,10 @@ public: { for (FunctionRefVector::iterator i = it->second.begin(); i != it->second.end();) { - uint32 counter = (*i).second; - if (counter > 1) + Binding &b = (*i); + if (b.isTemporary && b.remainingShots == 0) { - counter--; - (*i).second = counter; - i++; - } - else if (counter == 1) - { - luaL_unref(E.L, LUA_REGISTRYINDEX, (*i).first); + luaL_unref(E.L, LUA_REGISTRYINDEX, b.functionReference); i = it->second.erase(i); } else @@ -195,7 +193,7 @@ public: void Insert(uint32 entryId, int eventId, int funcRef, uint32 shots) // Inserts a new registered event { - Bindings[entryId][eventId].push_back(std::make_pair(funcRef, shots)); + Bindings[entryId][eventId].push_back(Binding(funcRef, shots)); } // Returns true if the entry has registered binds diff --git a/HookMgr.cpp b/HookMgr.cpp index 292ab84..50772d7 100644 --- a/HookMgr.cpp +++ b/HookMgr.cpp @@ -51,8 +51,17 @@ using namespace HookMgr; const char* _LuaBindType = this->BINDMAP->groupName; \ uint32 _LuaEvent = EVENT; \ int _LuaStackTop = lua_gettop(L); \ + bool _LuaTemporariesDied = false; \ for (size_t i = 0; i < this->BINDMAP->Bindings[_LuaEvent].size(); ++i) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[_LuaEvent][i].first)); \ + { \ + if (this->BINDMAP->Bindings[_LuaEvent][i].isTemporary) \ + { \ + this->BINDMAP->Bindings[_LuaEvent][i].remainingShots--; \ + if (this->BINDMAP->Bindings[_LuaEvent][i].remainingShots == 0) \ + _LuaTemporariesDied = true; \ + } \ + lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[_LuaEvent][i].functionReference)); \ + } \ int _LuaFuncTop = lua_gettop(L); \ int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \ Eluna::Push(L, _LuaEvent); @@ -86,8 +95,17 @@ using namespace HookMgr; const char* _LuaBindType = _LuaBind->groupName; \ uint32 _LuaEvent = EVENT; \ int _LuaStackTop = lua_gettop(L); \ + bool _LuaTemporariesDied = false; \ for (size_t i = 0; i < this->BINDMAP->Bindings[ENTRY][_LuaEvent].size(); ++i) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].first)); \ + { \ + if (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].isTemporary) \ + { \ + this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].remainingShots--; \ + if (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].remainingShots == 0) \ + _LuaTemporariesDied = true; \ + } \ + lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i].functionReference)); \ + } \ int _LuaFuncTop = lua_gettop(L); \ int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \ Eluna::Push(L, _LuaEvent); @@ -123,7 +141,8 @@ 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 (_LuaTemporariesDied) \ + _LuaBind->UpdateTemporaryBindings(); \ if (!this->event_level) \ this->InvalidateObjects(); // Invalidate objects on outermost hook call