Allow multiple callbacks for the same entry/event combo.

The callbacks will be called in reverse-order of registration.
This commit is contained in:
Patman64
2014-12-15 02:16:37 -05:00
parent 967a8045eb
commit 3ff4c5f26e
2 changed files with 36 additions and 33 deletions

View File

@@ -93,7 +93,8 @@ template<typename T>
class EntryBind : public ElunaBind
{
public:
typedef std::map<int, int> ElunaBindingMap;
typedef std::vector<int> FunctionRefVector;
typedef std::map<int, FunctionRefVector> ElunaBindingMap;
typedef UNORDERED_MAP<uint32, ElunaBindingMap> ElunaEntryMap;
EntryBind(const char* bindGroupName, Eluna& _E) : ElunaBind(bindGroupName, _E)
@@ -105,8 +106,12 @@ public:
{
for (ElunaEntryMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr)
{
for (ElunaBindingMap::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
luaL_unref(E.L, LUA_REGISTRYINDEX, it->second);
for (ElunaBindingMap::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));
it->second.clear();
}
itr->second.clear();
}
Bindings.clear();
@@ -114,27 +119,7 @@ public:
void Insert(uint32 entryId, int eventId, int funcRef) // Inserts a new registered event
{
if (Bindings[entryId][eventId])
{
luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // free the unused ref
luaL_error(E.L, "A function is already registered for entry (%d) event (%d)", entryId, eventId);
}
else
Bindings[entryId][eventId] = funcRef;
}
// Gets the function ref of an entry for an event
int GetBind(uint32 entryId, T eventId) const
{
if (Bindings.empty())
return 0;
ElunaEntryMap::const_iterator itr = Bindings.find(entryId);
if (itr == Bindings.end() || itr->second.empty())
return 0;
ElunaBindingMap::const_iterator itr2 = itr->second.find(eventId);
if (itr2 == itr->second.end())
return 0;
return itr2->second;
Bindings[entryId][eventId].push_back(funcRef);
}
// Gets the binding std::map containing all registered events with the function refs for the entry
@@ -150,14 +135,19 @@ public:
}
// Returns true if the entry has registered binds
bool HasBinds(uint32 entryId) const
bool HasEvents(uint32 entryId, int eventId) const
{
if (Bindings.empty())
return false;
return Bindings.find(entryId) != Bindings.end();
ElunaEntryMap::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;
ElunaEntryMap Bindings; // Binding store Bindings[entryId][eventId] = {funcRef};
};
#endif

View File

@@ -29,7 +29,7 @@ using namespace HookMgr;
/*
* Call model for EventBind:
*
*
* // Begin the call if should
* EVENT_BEGIN(bindmap, eventid, return returnvalue);
* // push arguments
@@ -78,22 +78,35 @@ using namespace HookMgr;
// RET is a return statement
#define ENTRY_BEGIN(BINDMAP, ENTRY, EVENT, RET) \
int _Luabind = this->BINDMAP->GetBind(ENTRY, EVENT); \
if (!_Luabind) \
if (!BINDMAP->HasEvents(ENTRY, EVENT)) \
RET; \
lua_State* L = this->L; \
const char* _LuaBindType = this->BINDMAP->groupName; \
uint32 _LuaEvent = EVENT; \
int _LuaStackTop = lua_gettop(L); \
lua_rawgeti(L, LUA_REGISTRYINDEX, _Luabind); \
for (size_t i = 0; i < this->BINDMAP->Bindings[ENTRY][_LuaEvent].size(); ++i) \
lua_rawgeti(L, LUA_REGISTRYINDEX, (this->BINDMAP->Bindings[ENTRY][_LuaEvent][i])); \
int _LuaFuncTop = lua_gettop(L); \
int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \
Eluna::Push(L, _LuaEvent);
#define ENTRY_EXECUTE(RETVALS) \
int _LuaReturnValues = RETVALS; \
int _LuaParams = lua_gettop(L) - _LuaStackTop - 1; \
Eluna::ExecuteCall(_LuaParams, _LuaReturnValues);
int _LuaParams = lua_gettop(L) - _LuaFuncTop; \
if (_LuaParams < 2) \
{ \
ELUNA_LOG_ERROR("[Eluna]: Executing event %u for %s, params was %i. Report to devs", _LuaEvent, _LuaBindType, _LuaParams); \
} \
for (int j = _LuaFuncTop-_LuaStackTop; j > 0; --j) \
{ \
for (int i = 0; i <= _LuaParams; ++i) \
lua_pushvalue(L, _LuaFuncTop+i); \
Eluna::ExecuteCall(_LuaParams, _LuaReturnValues); \
lua_remove(L, _LuaFuncTop--); \
} \
for (int i = _LuaParams; i > 0; --i) \
if (!lua_isnone(L, i)) \
lua_remove(L, i);
#define FOR_RETS(IT) \
for (int IT = _LuaStackTop + 1; IT <= lua_gettop(L); ++IT)