mirror of
https://github.com/azerothcore/mod-ale
synced 2025-11-29 15:38:17 +08:00
Allow multiple callbacks for the same entry/event combo.
The callbacks will be called in reverse-order of registration.
This commit is contained in:
@@ -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
|
||||
|
||||
25
HookMgr.cpp
25
HookMgr.cpp
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user