diff --git a/ElunaBinding.h b/ElunaBinding.h
index 831e1f4..d65a94e 100644
--- a/ElunaBinding.h
+++ b/ElunaBinding.h
@@ -17,7 +17,7 @@ extern "C"
#include "lauxlib.h"
};
-class ElunaBind
+class ElunaBind : public ElunaUtil::RWLockable
{
public:
struct Binding
@@ -71,6 +71,8 @@ public:
// unregisters all registered functions and clears all registered events from the bind std::maps (reset)
void Clear() override
{
+ WriteGuard guard(GetLock());
+
for (EventToFunctionsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr)
{
FunctionRefVector& funcrefvec = itr->second;
@@ -83,6 +85,8 @@ public:
void Clear(uint32 event_id)
{
+ WriteGuard guard(GetLock());
+
for (FunctionRefVector::iterator itr = Bindings[event_id].begin(); itr != Bindings[event_id].end(); ++itr)
delete *itr;
Bindings[event_id].clear();
@@ -91,6 +95,8 @@ public:
// 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)
{
+ WriteGuard guard(GetLock());
+
for (FunctionRefVector::iterator it = Bindings[event_id].begin(); it != Bindings[event_id].end();)
{
FunctionRefVector::iterator it_old = it++;
@@ -115,12 +121,15 @@ public:
void Insert(int eventId, int funcRef, uint32 shots) // Inserts a new registered event
{
+ WriteGuard guard(GetLock());
Bindings[eventId].push_back(new Binding(E, funcRef, shots));
}
// Checks if there are events for ID
- bool HasEvents(T eventId) const
+ bool HasEvents(T eventId)
{
+ ReadGuard guard(GetLock());
+
if (Bindings.empty())
return false;
if (Bindings.find(eventId) == Bindings.end())
@@ -144,6 +153,8 @@ public:
// unregisters all registered functions and clears all registered events from the bindmap
void Clear() override
{
+ WriteGuard guard(GetLock());
+
for (EntryToEventsMap::iterator itr = Bindings.begin(); itr != Bindings.end(); ++itr)
{
EventToFunctionsMap& funcmap = itr->second;
@@ -161,6 +172,8 @@ public:
void Clear(uint32 entry, uint32 event_id)
{
+ WriteGuard guard(GetLock());
+
for (FunctionRefVector::iterator itr = Bindings[entry][event_id].begin(); itr != Bindings[entry][event_id].end(); ++itr)
delete *itr;
Bindings[entry][event_id].clear();
@@ -169,6 +182,8 @@ public:
// 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)
{
+ WriteGuard guard(GetLock());
+
for (FunctionRefVector::iterator it = Bindings[entry][event_id].begin(); it != Bindings[entry][event_id].end();)
{
FunctionRefVector::iterator it_old = it++;
@@ -196,12 +211,15 @@ public:
void Insert(uint32 entryId, int eventId, int funcRef, uint32 shots) // Inserts a new registered event
{
+ WriteGuard guard(GetLock());
Bindings[entryId][eventId].push_back(new Binding(E, funcRef, shots));
}
// Returns true if the entry has registered binds
- bool HasEvents(uint32 entryId, int eventId) const
+ bool HasEvents(T eventId, uint32 entryId)
{
+ ReadGuard guard(GetLock());
+
if (Bindings.empty())
return false;
@@ -212,8 +230,10 @@ public:
return itr->second.find(eventId) != itr->second.end();
}
- bool HasEvents(uint32 entryId) const
+ bool HasEvents(uint32 entryId)
{
+ ReadGuard guard(GetLock());
+
if (Bindings.empty())
return false;
diff --git a/ElunaEventMgr.cpp b/ElunaEventMgr.cpp
index 48c4ca3..cc765c9 100644
--- a/ElunaEventMgr.cpp
+++ b/ElunaEventMgr.cpp
@@ -26,7 +26,7 @@ LuaEvent::~LuaEvent()
void LuaEvent::Execute()
{
- ELUNA_LOCK(*events->E);
+ LOCK_ELUNA;
// In multithread get map from object and the map's lua state
lua_rawgeti((*events->E)->L, LUA_REGISTRYINDEX, funcRef);
Eluna::Push((*events->E)->L, funcRef);
@@ -45,7 +45,7 @@ ElunaEventProcessor::ElunaEventProcessor(Eluna** _E, WorldObject* _obj) : m_time
{
if (obj)
{
- EventMgr::WriteGuard lock((*E)->eventMgr->GetLock());
+ EventMgr::WriteGuard guard((*E)->eventMgr->GetLock());
(*E)->eventMgr->processors.insert(this);
}
}
@@ -56,7 +56,7 @@ ElunaEventProcessor::~ElunaEventProcessor()
if (obj && Eluna::initialized)
{
- EventMgr::WriteGuard lock((*E)->eventMgr->GetLock());
+ EventMgr::WriteGuard guard((*E)->eventMgr->GetLock());
(*E)->eventMgr->processors.erase(this);
}
}
@@ -133,7 +133,7 @@ EventMgr::EventMgr(Eluna** _E) : globalProcessor(new ElunaEventProcessor(_E, NUL
EventMgr::~EventMgr()
{
{
- ReadGuard lock(GetLock());
+ ReadGuard guard(GetLock());
if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvents_internal();
@@ -145,7 +145,7 @@ EventMgr::~EventMgr()
void EventMgr::RemoveEvents()
{
- ReadGuard lock(GetLock());
+ ReadGuard guard(GetLock());
if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvents();
@@ -154,7 +154,7 @@ void EventMgr::RemoveEvents()
void EventMgr::RemoveEvent(int eventId)
{
- ReadGuard lock(GetLock());
+ ReadGuard guard(GetLock());
if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvent(eventId);
diff --git a/ElunaUtility.h b/ElunaUtility.h
index b56ade6..1ca5b29 100644
--- a/ElunaUtility.h
+++ b/ElunaUtility.h
@@ -119,9 +119,9 @@ namespace ElunaUtil
/*
* Usage:
* Inherit this class, then when needing lock, use
- * ReadGuard lock(_lock);
+ * ReadGuard guard(GetLock());
* or
- * WriteGuard lock(_lock);
+ * WriteGuard guard(GetLock());
*
* The lock is automatically released at end of scope
*/
diff --git a/HookMgr.cpp b/HookMgr.cpp
index 92371be..b6ce2f2 100644
--- a/HookMgr.cpp
+++ b/HookMgr.cpp
@@ -1,8 +1,8 @@
/*
-* Copyright (C) 2010 - 2015 Eluna Lua Engine
-* This program is free software licensed under GPL version 3
-* Please see the included DOCS/LICENSE.md for more information
-*/
+ * Copyright (C) 2010 - 2015 Eluna Lua Engine
+ * This program is free software licensed under GPL version 3
+ * Please see the included DOCS/LICENSE.md for more information
+ */
#include "HookMgr.h"
#include "LuaEngine.h"
@@ -28,165 +28,301 @@ struct ScriptedAI;
using namespace HookMgr;
/*
- * Call model for EventBind:
+ * A hook should be written in one of the following forms:
*
- * // Begin the call if should
- * EVENT_BEGIN(bindmap, eventid, return returnvalue);
- * // push arguments
- * Push(L, pPlayer);
- * EVENT_EXECUTE(returnedargs);
- * FOR_RET(iter)
- * {
- * // process returned arguments
- * }
- * ENDCALL();
+ * A. If results will be IGNORED:
+ *
+ * // Return early if there are no bindings.
+ * if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
+ * return;
+ *
+ * // Lock out any other threads.
+ * LOCK_ELUNA;
+ *
+ * // Push extra arguments, if any.
+ * Push(a);
+ * Push(b);
+ * Push(c);
+ *
+ * // Call all event handlers.
+ * CallAllFunctions(WhateverBindings, SOME_EVENT_TYPE);
+ *
+ *
+ * B. If results will be USED:
+ *
+ * // Return early if there are no bindings.
+ * if (!WhateverBindings->HasEvents(SOME_EVENT_TYPE))
+ * return;
+ *
+ * // Lock out any other threads.
+ * LOCK_ELUNA;
+ *
+ * // Push extra arguments, if any.
+ * Push(a);
+ * Push(b);
+ * Push(c);
+ *
+ * // Setup the stack and get the number of functions pushed.
+ * // Last argument is 3 because we did 3 Pushes.
+ * int n = SetupStack(WhateverBindings, SOME_EVENT_TYPE, 3);
+ *
+ * // Call each event handler in order and check results.
+ * while (n > 0)
+ * {
+ * // Call an event handler and decrement the function counter afterward.
+ * // Second-last argument is 3 because we did 3 Pushes.
+ * // Last argument is 2 because we want 2 results.
+ * int r = CallOneFunction(n--, 3, 2);
+ *
+ * // Results can be popped using `r`.
+ * int first = CHECKVAL(L, r + 0);
+ * int second = CHECKVAL(L, r + 1);
+ *
+ * // Pop the results off the stack.
+ * lua_pop(L, 2);
+ * }
+ *
+ * // Clean-up the stack. Argument is 3 because we did 3 Pushes.
+ * CleanUpStack(3);
*/
-// RET is a return statement
-#define EVENT_BEGIN(BINDMAP, EVENT, RET) \
- if (!BINDMAP->HasEvents(EVENT)) \
- RET; \
- ELUNA_LOCK(this); \
- const char* _LuaBindType = this->BINDMAP->groupName; \
- uint32 _LuaEvent = EVENT; \
- int _LuaStackTop = lua_gettop(L); \
- this->BINDMAP->PushFuncRefs(L, _LuaEvent); \
- int _LuaFuncTop = lua_gettop(L); \
- int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \
- Eluna::Push(L, _LuaEvent);
+/*
+ * Sets up the stack so that event handlers can be called.
+ *
+ * Returns the number of functions that were pushed onto the stack.
+ *
+ * Use the simpler overloads for just EventBind or EntryBind instead of this overload in hooks.
+ */
+template
+int Eluna::SetupStack(EventBind* event_bindings, EntryBind* entry_bindings, T event_id, uint32 entry, int number_of_arguments)
+{
+ // Ensure that if `entry_bindings` is not NULL, a valid entry is supplied.
+ ASSERT(!entry_bindings || (entry_bindings && entry > 0));
+ ASSERT(number_of_arguments == this->push_counter);
+ // Stack: [arguments]
-// use LUA_MULTRET for multiple return values
-// return values will be at top of stack if any
-#define EVENT_EXECUTE(RETVALS) \
- int _LuaReturnValues = RETVALS; \
- int _LuaParams = lua_gettop(L) - _LuaFuncTop; \
- if (_LuaParams < 1) \
- { \
- 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);
+ Push(event_id);
+ this->push_counter = 0;
+ ++number_of_arguments;
+ // Stack: [arguments], event_id
-// RET is a return statement
-#define ENTRY_BEGIN(BINDMAP, ENTRY, EVENT, RET) \
- if (!BINDMAP->HasEvents(ENTRY, EVENT)) \
- RET; \
- ELUNA_LOCK(this); \
- const char* _LuaBindType = this->BINDMAP->groupName; \
- uint32 _LuaEvent = EVENT; \
- int _LuaStackTop = lua_gettop(L); \
- this->BINDMAP->PushFuncRefs(L, _LuaEvent, ENTRY); \
- int _LuaFuncTop = lua_gettop(L); \
- int _LuaFuncCount = _LuaFuncTop-_LuaStackTop; \
- Eluna::Push(L, _LuaEvent);
+ int arguments_top = lua_gettop(L);
+ int first_argument_index = arguments_top - number_of_arguments + 1;
+ ASSERT(arguments_top >= number_of_arguments);
-#define ENTRY_EXECUTE(RETVALS) \
- int _LuaReturnValues = RETVALS; \
- 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);
+ lua_insert(L, first_argument_index);
+ // Stack: event_id, [arguments]
-#define FOR_RETS(IT) \
- for (int IT = _LuaStackTop + 1; IT <= lua_gettop(L); ++IT)
+ if (event_bindings)
+ event_bindings->PushFuncRefs(L, (int)event_id);
-#define ENDCALL() \
- if (lua_gettop(L) < _LuaStackTop) \
- { \
- ELUNA_LOG_ERROR("[Eluna]: Ending event %u for %s, stack top was %i and was supposed to be >= %i. Report to devs", _LuaEvent, _LuaBindType, lua_gettop(L), _LuaStackTop); \
- } \
- if (_LuaReturnValues != LUA_MULTRET && lua_gettop(L) > _LuaStackTop + _LuaFuncCount * _LuaReturnValues) \
- { \
- 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); \
- if (!this->event_level) \
- this->InvalidateObjects(); // Invalidate objects on outermost hook call
+ if (entry_bindings)
+ entry_bindings->PushFuncRefs(L, (int)event_id, entry);
+ // Stack: event_id, [arguments], [functions]
+
+ int number_of_functions = lua_gettop(L) - arguments_top;
+ return number_of_functions;
+}
+
+/*
+ * Replace one of the arguments pushed before `SetupStack` with a new value.
+ */
+template
+void Eluna::ReplaceArgument(T value, uint8 index)
+{
+ ASSERT(index < lua_gettop(L) && index > 0);
+ // Stack: event_id, [arguments], [functions], [results]
+
+ Eluna::Push(L, value);
+ // Stack: event_id, [arguments], [functions], [results], value
+
+ lua_replace(L, index + 1);
+ // Stack: event_id, [arguments and value], [functions], [results]
+}
+
+/*
+ * Call a single event handler that was put on the stack with `Setup` and removes it from the stack.
+ *
+ * The caller is responsible for keeping track of how many times this should be called.
+ */
+int Eluna::CallOneFunction(int number_of_functions, int number_of_arguments, int number_of_results)
+{
+ ++number_of_arguments; // Caller doesn't know about `event_id`.
+ ASSERT(number_of_functions > 0 && number_of_arguments > 0 && number_of_results >= 0);
+ // Stack: event_id, [arguments], [functions]
+
+ int functions_top = lua_gettop(L);
+ int first_function_index = functions_top - number_of_functions + 1;
+ int arguments_top = first_function_index - 1;
+ int first_argument_index = arguments_top - number_of_arguments + 1;
+
+ // Copy the arguments from the bottom of the stack to the top.
+ for (int argument_index = first_argument_index; argument_index <= arguments_top; ++argument_index)
+ {
+ lua_pushvalue(L, argument_index);
+ }
+ // Stack: event_id, [arguments], [functions], event_id, [arguments]
+
+ ExecuteCall(number_of_arguments, number_of_results);
+ --functions_top;
+ // Stack: event_id, [arguments], [functions - 1], [results]
+
+ return functions_top + 1; // Return the location of the first result (if any exist).
+}
+
+/*
+ * Cleans up the stack, effectively undoing all Push calls and the Setup call.
+ */
+void Eluna::CleanUpStack(int number_of_arguments)
+{
+ // Stack: event_id, [arguments]
+
+ lua_pop(L, number_of_arguments + 1); // Add 1 because the caller doesn't know about `event_id`.
+ // Stack: (empty)
+
+ if (event_level == 0)
+ InvalidateObjects();
+}
+
+/*
+ * Call all event handlers registered to the event ID/entry combination and ignore any results.
+ */
+template
+void Eluna::CallAllFunctions(EventBind* event_bindings, EntryBind* entry_bindings, T event_id, uint32 entry)
+{
+ int number_of_arguments = this->push_counter;
+ // Stack: [arguments]
+
+ int number_of_functions = SetupStack(event_bindings, entry_bindings, event_id, entry, number_of_arguments);
+ // Stack: event_id, [arguments], [functions]
+
+ while (number_of_functions > 0)
+ {
+ CallOneFunction(number_of_functions, number_of_arguments, 0);
+ --number_of_functions;
+ // Stack: event_id, [arguments], [functions - 1]
+ }
+ // Stack: event_id, [arguments]
+
+ CleanUpStack(number_of_arguments);
+ // Stack: (empty)
+}
+
+/*
+ * Call all event handlers registered to the event ID/entry combination,
+ * and returns `default_value` if ALL event handlers returned `default_value`,
+ * otherwise returns the opposite of `default_value`.
+ */
+template
+bool Eluna::CallAllFunctionsBool(EventBind* event_bindings, EntryBind* entry_bindings, T event_id, uint32 entry, bool default_value)
+{
+ bool result = default_value;
+ // Note: number_of_arguments here does not count in eventID, which is pushed in SetupStack
+ int number_of_arguments = this->push_counter;
+ // Stack: [arguments]
+
+ int number_of_functions = SetupStack(event_bindings, entry_bindings, event_id, entry, number_of_arguments);
+ // Stack: event_id, [arguments], [functions]
+
+ while (number_of_functions > 0)
+ {
+ int r = CallOneFunction(number_of_functions, number_of_arguments, 1);
+ --number_of_functions;
+ // Stack: event_id, [arguments], [functions - 1], result
+
+ if (lua_isboolean(L, r) && (lua_toboolean(L, r) == 1) != default_value)
+ result = !default_value;
+
+ lua_pop(L, 1);
+ // Stack: event_id, [arguments], [functions - 1]
+ }
+ // Stack: event_id, [arguments]
+
+ CleanUpStack(number_of_arguments);
+ // Stack: (empty)
+ return result;
+}
void Eluna::OnLuaStateClose()
{
- EVENT_BEGIN(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_CLOSE, return);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_CLOSE))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_CLOSE);
}
void Eluna::OnLuaStateOpen()
{
- EVENT_BEGIN(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_OPEN, return);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(ELUNA_EVENT_ON_LUA_STATE_OPEN))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, ELUNA_EVENT_ON_LUA_STATE_OPEN);
}
// areatrigger
bool Eluna::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger)
{
- EVENT_BEGIN(ServerEventBindings, TRIGGER_EVENT_ON_TRIGGER, return false);
- Push(L, pPlayer);
- Push(L, pTrigger->id);
- EVENT_EXECUTE(0);
- ENDCALL();
- return false;
+ if (!ServerEventBindings->HasEvents(TRIGGER_EVENT_ON_TRIGGER))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pTrigger->id);
+ return CallAllFunctionsBool(ServerEventBindings, TRIGGER_EVENT_ON_TRIGGER);
}
// weather
void Eluna::OnChange(Weather* weather, WeatherState state, float grade)
{
- EVENT_BEGIN(ServerEventBindings, WEATHER_EVENT_ON_CHANGE, return);
- Push(L, weather->GetZone());
- Push(L, state);
- Push(L, grade);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WEATHER_EVENT_ON_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(weather->GetZone());
+ Push(state);
+ Push(grade);
+ CallAllFunctions(ServerEventBindings, WEATHER_EVENT_ON_CHANGE);
}
// Auction House
void Eluna::OnAdd(AuctionHouseObject* ah)
{
- EVENT_BEGIN(ServerEventBindings, AUCTION_EVENT_ON_ADD, return);
- Push(L, (ah));
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_ADD))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_ADD);
}
void Eluna::OnRemove(AuctionHouseObject* ah)
{
- EVENT_BEGIN(ServerEventBindings, AUCTION_EVENT_ON_REMOVE, return);
- Push(L, (ah));
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_REMOVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_REMOVE);
}
void Eluna::OnSuccessful(AuctionHouseObject* ah)
{
- EVENT_BEGIN(ServerEventBindings, AUCTION_EVENT_ON_SUCCESSFUL, return);
- Push(L, (ah));
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_SUCCESSFUL))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_SUCCESSFUL);
}
void Eluna::OnExpire(AuctionHouseObject* ah)
{
- EVENT_BEGIN(ServerEventBindings, AUCTION_EVENT_ON_EXPIRE, return);
- Push(L, (ah));
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(AUCTION_EVENT_ON_EXPIRE))
+ return;
+
+ LOCK_ELUNA;
+ Push(ah);
+ CallAllFunctions(ServerEventBindings, AUCTION_EVENT_ON_EXPIRE);
}
// Packet
@@ -202,45 +338,55 @@ bool Eluna::OnPacketSend(WorldSession* session, WorldPacket& packet)
}
void Eluna::OnPacketSendAny(Player* player, WorldPacket& packet, bool& result)
{
- EVENT_BEGIN(ServerEventBindings, SERVER_EVENT_ON_PACKET_SEND, return);
- Push(L, new WorldPacket(packet));
- Push(L, player);
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ if (!ServerEventBindings->HasEvents(SERVER_EVENT_ON_PACKET_SEND))
+ return;
+
+ LOCK_ELUNA;
+ Push(new WorldPacket(packet));
+ Push(player);
+ int n = SetupStack(ServerEventBindings, SERVER_EVENT_ON_PACKET_SEND, 2);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isuserdata(L, i))
- if (WorldPacket* data = CHECKOBJ(L, i, false))
- packet = *data;
- if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 2, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isuserdata(L, r + 1))
+ if (WorldPacket* data = CHECKOBJ(L, r + 1, true))
+ packet = *data;
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(2);
}
void Eluna::OnPacketSendOne(Player* player, WorldPacket& packet, bool& result)
{
- ENTRY_BEGIN(PacketEventBindings, OpcodesList(packet.GetOpcode()), PACKET_EVENT_ON_PACKET_SEND, return);
- Push(L, new WorldPacket(packet));
- Push(L, player);
- ENTRY_EXECUTE(2);
- FOR_RETS(i)
+ if (!PacketEventBindings->HasEvents(PACKET_EVENT_ON_PACKET_SEND, packet.GetOpcode()))
+ return;
+
+ LOCK_ELUNA;
+ Push(new WorldPacket(packet));
+ Push(player);
+ int n = SetupStack(PacketEventBindings, PACKET_EVENT_ON_PACKET_SEND, OpcodesList(packet.GetOpcode()), 2);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isuserdata(L, i))
- if (WorldPacket* data = CHECKOBJ(L, i, false))
- packet = *data;
- if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 2, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isuserdata(L, r + 1))
+ if (WorldPacket* data = CHECKOBJ(L, r + 1, true))
+ packet = *data;
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(2);
}
bool Eluna::OnPacketReceive(WorldSession* session, WorldPacket& packet)
@@ -255,105 +401,127 @@ bool Eluna::OnPacketReceive(WorldSession* session, WorldPacket& packet)
}
void Eluna::OnPacketReceiveAny(Player* player, WorldPacket& packet, bool& result)
{
- EVENT_BEGIN(ServerEventBindings, SERVER_EVENT_ON_PACKET_RECEIVE, return);
- Push(L, new WorldPacket(packet));
- Push(L, player);
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ if (!ServerEventBindings->HasEvents(SERVER_EVENT_ON_PACKET_RECEIVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(new WorldPacket(packet));
+ Push(player);
+ int n = SetupStack(ServerEventBindings, SERVER_EVENT_ON_PACKET_RECEIVE, 2);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isuserdata(L, i))
- if (WorldPacket* data = CHECKOBJ(L, i, false))
- packet = *data;
- if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 2, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isuserdata(L, r + 1))
+ if (WorldPacket* data = CHECKOBJ(L, r + 1, true))
+ packet = *data;
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(2);
}
void Eluna::OnPacketReceiveOne(Player* player, WorldPacket& packet, bool& result)
{
- ENTRY_BEGIN(PacketEventBindings, OpcodesList(packet.GetOpcode()), PACKET_EVENT_ON_PACKET_RECEIVE, return);
- Push(L, new WorldPacket(packet));
- Push(L, player);
- ENTRY_EXECUTE(2);
- FOR_RETS(i)
+ if (!PacketEventBindings->HasEvents(PACKET_EVENT_ON_PACKET_RECEIVE, packet.GetOpcode()))
+ return;
+
+ LOCK_ELUNA;
+ Push(new WorldPacket(packet));
+ Push(player);
+ int n = SetupStack(PacketEventBindings, PACKET_EVENT_ON_PACKET_RECEIVE, OpcodesList(), 2);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isuserdata(L, i))
- if (WorldPacket* data = CHECKOBJ(L, i, false))
- packet = *data;
- if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 2, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isuserdata(L, r + 1))
+ if (WorldPacket* data = CHECKOBJ(L, r + 1, true))
+ packet = *data;
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(2);
}
// AddOns
bool Eluna::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* receiver, Guild* guild, Group* group, Channel* channel)
{
- EVENT_BEGIN(ServerEventBindings, ADDON_EVENT_ON_MESSAGE, return false);
- Push(L, sender);
- Push(L, type);
+ if (!ServerEventBindings->HasEvents(ADDON_EVENT_ON_MESSAGE))
+ return true;
+
+ LOCK_ELUNA;
+ Push(sender);
+ Push(type);
const char* c_msg = msg.c_str();
- Push(L, strtok((char*)c_msg, "\t")); // prefix
- Push(L, strtok(NULL, "")); // msg
+ Push(strtok((char*)c_msg, "\t")); // prefix
+ Push(strtok(NULL, "")); // msg
if (receiver)
- Push(L, receiver);
+ Push(receiver);
else if (guild)
- Push(L, guild);
+ Push(guild);
else if (group)
- Push(L, group);
+ Push(group);
else if (channel)
- Push(L, channel->GetChannelId());
+ Push(channel->GetChannelId());
else
- Push(L);
- EVENT_EXECUTE(0);
- ENDCALL();
- return true;
+ Push();
+
+ return CallAllFunctionsBool(ServerEventBindings, ADDON_EVENT_ON_MESSAGE, true);
}
void Eluna::OnOpenStateChange(bool open)
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_OPEN_STATE_CHANGE, return);
- Push(L, open);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_OPEN_STATE_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(open);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_OPEN_STATE_CHANGE);
}
void Eluna::OnConfigLoad(bool reload)
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_CONFIG_LOAD, return);
- Push(L, reload);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_CONFIG_LOAD))
+ return;
+
+ LOCK_ELUNA;
+ Push(reload);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_CONFIG_LOAD);
}
void Eluna::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask)
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_INIT, return);
- Push(L, code);
- Push(L, mask);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_INIT))
+ return;
+
+ LOCK_ELUNA;
+ Push(code);
+ Push(mask);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_INIT);
}
void Eluna::OnShutdownCancel()
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_CANCEL, return);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN_CANCEL))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN_CANCEL);
}
void Eluna::OnWorldUpdate(uint32 diff)
{
+ LOCK_ELUNA;
+
if (reload)
{
ReloadEluna();
@@ -362,80 +530,95 @@ void Eluna::OnWorldUpdate(uint32 diff)
eventMgr->globalProcessor->Update(diff);
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_UPDATE, return);
- Push(L, diff);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_UPDATE))
+ return;
+
+ Push(diff);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_UPDATE);
}
void Eluna::OnStartup()
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_STARTUP, return);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_STARTUP))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_STARTUP);
}
void Eluna::OnShutdown()
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN, return);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_SHUTDOWN))
+ return;
+
+ LOCK_ELUNA;
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_SHUTDOWN);
}
void Eluna::HandleGossipSelectOption(Player* pPlayer, Item* item, uint32 sender, uint32 action, const std::string& code)
{
- ENTRY_BEGIN(ItemGossipBindings, item->GetEntry(), GOSSIP_EVENT_ON_SELECT, return);
+ if (!ItemGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, item->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, item);
- Push(L, sender);
- Push(L, action);
+
+ Push(pPlayer);
+ Push(item);
+ Push(sender);
+ Push(action);
if (code.empty())
- Push(L);
+ Push();
else
- Push(L, code);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ Push(code);
+
+ CallAllFunctions(ItemGossipBindings, GOSSIP_EVENT_ON_SELECT, item->GetEntry());
}
void Eluna::HandleGossipSelectOption(Player* pPlayer, uint32 menuId, uint32 sender, uint32 action, const std::string& code)
{
- ENTRY_BEGIN(playerGossipBindings, menuId, GOSSIP_EVENT_ON_SELECT, return);
+ if (!playerGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, menuId))
+ return;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer); // receiver
- Push(L, pPlayer); // sender, just not to mess up the amount of args.
- Push(L, sender);
- Push(L, action);
+
+ Push(pPlayer); // receiver
+ Push(pPlayer); // sender, just not to mess up the amount of args.
+ Push(sender);
+ Push(action);
if (code.empty())
- Push(L);
+ Push();
else
- Push(L, code);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ Push(code);
+
+ CallAllFunctions(playerGossipBindings, GOSSIP_EVENT_ON_SELECT, menuId);
}
// item
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, Item* pTarget)
{
- ENTRY_BEGIN(ItemEventBindings, pTarget->GetEntry(), ITEM_EVENT_ON_DUMMY_EFFECT, return false);
- Push(L, pCaster);
- Push(L, spellId);
- Push(L, effIndex);
- Push(L, pTarget);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pCaster);
+ Push(spellId);
+ Push(effIndex);
+ Push(pTarget);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
}
bool Eluna::OnQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest)
{
- ENTRY_BEGIN(ItemEventBindings, pItem->GetEntry(), ITEM_EVENT_ON_QUEST_ACCEPT, return false);
- Push(L, pPlayer);
- Push(L, pItem);
- Push(L, pQuest);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+ Push(pQuest);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_QUEST_ACCEPT, pItem->GetEntry());
}
bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
@@ -470,80 +653,73 @@ bool Eluna::OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
bool Eluna::OnItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets)
{
- bool result = true;
- ENTRY_BEGIN(ItemEventBindings, pItem->GetEntry(), ITEM_EVENT_ON_USE, return result);
- Push(L, pPlayer);
- Push(L, pItem);
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_USE, pItem->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
#ifndef TRINITY
if (GameObject* target = targets.getGOTarget())
- Push(L, target);
+ Push(target);
else if (Item* target = targets.getItemTarget())
- Push(L, target);
+ Push(target);
else if (Corpse* target = pPlayer->GetMap()->GetCorpse(targets.getCorpseTargetGuid()))
- Push(L, target);
+ Push(target);
else if (Unit* target = targets.getUnitTarget())
- Push(L, target);
+ Push(target);
else
- Push(L);
+ Push();
#else
if (GameObject* target = targets.GetGOTarget())
- Push(L, target);
+ Push(target);
else if (Item* target = targets.GetItemTarget())
- Push(L, target);
+ Push(target);
else if (Corpse* target = targets.GetCorpseTarget())
- Push(L, target);
+ Push(target);
else if (Unit* target = targets.GetUnitTarget())
- Push(L, target);
+ Push(target);
else if (WorldObject* target = targets.GetObjectTarget())
- Push(L, target);
+ Push(target);
else
- Push(L);
+ Push();
#endif
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, result);
- }
- ENDCALL();
- return result;
+
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_USE, pItem->GetEntry());
}
bool Eluna::OnItemGossip(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/)
{
- bool result = true;
- ENTRY_BEGIN(ItemGossipBindings, pItem->GetEntry(), GOSSIP_EVENT_ON_HELLO, return result);
+ if (!ItemGossipBindings->HasEvents(GOSSIP_EVENT_ON_HELLO, pItem->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pItem);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, result);
- }
- ENDCALL();
- return result;
+ Push(pPlayer);
+ Push(pItem);
+ return CallAllFunctionsBool(ItemGossipBindings, GOSSIP_EVENT_ON_HELLO, pItem->GetEntry());
}
bool Eluna::OnExpire(Player* pPlayer, ItemTemplate const* pProto)
{
- ENTRY_BEGIN(ItemEventBindings, pProto->ItemId, ITEM_EVENT_ON_EXPIRE, return false);
- Push(L, pPlayer);
- Push(L, pProto->ItemId);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_EXPIRE, pProto->ItemId))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pProto->ItemId);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_EXPIRE, pProto->ItemId);
}
bool Eluna::OnRemove(Player* pPlayer, Item* item)
{
- ENTRY_BEGIN(ItemEventBindings, item->GetEntry(), ITEM_EVENT_ON_REMOVE, return false);
- Push(L, pPlayer);
- Push(L, item);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!ItemEventBindings->HasEvents(ITEM_EVENT_ON_REMOVE, item->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(item);
+ return CallAllFunctionsBool(ItemEventBindings, ITEM_EVENT_ON_REMOVE, item->GetEntry());
}
// Player
@@ -572,511 +748,612 @@ bool Eluna::OnCommand(Player* player, const char* text)
}
}
- bool result = true;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_COMMAND, return result);
- Push(L, player);
- Push(L, fullcmd);
- EVENT_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, result);
- }
- ENDCALL();
- return result;
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_COMMAND))
+ return true;
+
+ LOCK_ELUNA;
+ Push(player);
+ Push(fullcmd);
+ return CallAllFunctionsBool(PlayerEventBindings, PLAYER_EVENT_ON_COMMAND, true);
}
void Eluna::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, uint64 guid)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_ITEM, return);
- Push(L, pPlayer);
- Push(L, pItem);
- Push(L, count);
- Push(L, guid);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_ITEM))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+ Push(count);
+ Push(guid);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_ITEM);
}
void Eluna::OnLootMoney(Player* pPlayer, uint32 amount)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_MONEY, return);
- Push(L, pPlayer);
- Push(L, amount);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOOT_MONEY))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(amount);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOOT_MONEY);
}
void Eluna::OnFirstLogin(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_FIRST_LOGIN, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_FIRST_LOGIN))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_FIRST_LOGIN);
}
void Eluna::OnRepop(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_REPOP, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPOP))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_REPOP);
}
void Eluna::OnResurrect(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_RESURRECT, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_RESURRECT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_RESURRECT);
}
void Eluna::OnQuestAbandon(Player* pPlayer, uint32 questId)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_QUEST_ABANDON, return);
- Push(L, pPlayer);
- Push(L, questId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_QUEST_ABANDON))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(questId);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_QUEST_ABANDON);
}
void Eluna::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_EQUIP, return);
- Push(L, pPlayer);
- Push(L, pItem);
- Push(L, bag);
- Push(L, slot);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EQUIP))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pItem);
+ Push(bag);
+ Push(slot);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EQUIP);
}
InventoryResult Eluna::OnCanUseItem(const Player* pPlayer, uint32 itemEntry)
{
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CAN_USE_ITEM))
+ return EQUIP_ERR_OK;
+
+ LOCK_ELUNA;
InventoryResult result = EQUIP_ERR_OK;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_CAN_USE_ITEM, return result);
- Push(L, pPlayer);
- Push(L, itemEntry);
- EVENT_EXECUTE(1);
- FOR_RETS(i)
+ Push(pPlayer);
+ Push(itemEntry);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CAN_USE_ITEM, 2);
+
+ while (n > 0)
{
- if (!lua_isnumber(L, i))
- continue;
- uint32 res = CHECKVAL(L, i, EQUIP_ERR_OK);
- if (res != EQUIP_ERR_OK)
- result = (InventoryResult)res;
+ int r = CallOneFunction(n--, 2, 1);
+
+ if (lua_isnumber(L, r))
+ result = (InventoryResult)CHECKVAL(L, r);
+
+ lua_pop(L, 1);
}
- ENDCALL();
+
+ CleanUpStack(2);
return result;
}
void Eluna::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_ENTER_COMBAT, return);
- Push(L, pPlayer);
- Push(L, pEnemy);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_ENTER_COMBAT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pEnemy);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_ENTER_COMBAT);
}
void Eluna::OnPlayerLeaveCombat(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_LEAVE_COMBAT, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEAVE_COMBAT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEAVE_COMBAT);
}
void Eluna::OnPVPKill(Player* pKiller, Player* pKilled)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_KILL_PLAYER, return);
- Push(L, pKiller);
- Push(L, pKilled);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_PLAYER))
+ return;
+
+ LOCK_ELUNA;
+ Push(pKiller);
+ Push(pKilled);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_PLAYER);
}
void Eluna::OnCreatureKill(Player* pKiller, Creature* pKilled)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_KILL_CREATURE, return);
- Push(L, pKiller);
- Push(L, pKilled);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILL_CREATURE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pKiller);
+ Push(pKilled);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILL_CREATURE);
}
void Eluna::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_KILLED_BY_CREATURE, return);
- Push(L, pKiller);
- Push(L, pKilled);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_KILLED_BY_CREATURE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pKiller);
+ Push(pKilled);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_KILLED_BY_CREATURE);
}
void Eluna::OnLevelChanged(Player* pPlayer, uint8 oldLevel)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_LEVEL_CHANGE, return);
- Push(L, pPlayer);
- Push(L, oldLevel);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LEVEL_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(oldLevel);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LEVEL_CHANGE);
}
void Eluna::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_CHANGE, return);
- Push(L, pPlayer);
- Push(L, newPoints);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(newPoints);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_CHANGE);
}
void Eluna::OnTalentsReset(Player* pPlayer, bool noCost)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_RESET, return);
- Push(L, pPlayer);
- Push(L, noCost);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TALENTS_RESET))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(noCost);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TALENTS_RESET);
}
void Eluna::OnMoneyChanged(Player* pPlayer, int32& amount)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_MONEY_CHANGE, return);
- Push(L, pPlayer);
- Push(L, amount);
- EVENT_EXECUTE(1);
- FOR_RETS(i)
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MONEY_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(amount);
+ int amountIndex = lua_gettop(L);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_MONEY_CHANGE, 2);
+
+ while (n > 0)
{
- if (lua_isnumber(L, i))
- amount = CHECKVAL(L, i, amount);
+ int r = CallOneFunction(n--, 2, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
}
- ENDCALL();
+
+ CleanUpStack(2);
}
void Eluna::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_GIVE_XP, return);
- Push(L, pPlayer);
- Push(L, amount);
- Push(L, pVictim);
- EVENT_EXECUTE(1);
- FOR_RETS(i)
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GIVE_XP))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(amount);
+ Push(pVictim);
+ int amountIndex = lua_gettop(L) - 1;
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GIVE_XP, 3);
+
+ while (n > 0)
{
- if (lua_isnumber(L, i))
- amount = CHECKVAL(L, i, amount);
+ int r = CallOneFunction(n--, 3, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
}
- ENDCALL();
+
+ CleanUpStack(3);
}
void Eluna::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_REPUTATION_CHANGE, return);
- Push(L, pPlayer);
- Push(L, factionID);
- Push(L, standing);
- Push(L, incremental);
- EVENT_EXECUTE(1);
- FOR_RETS(i)
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_REPUTATION_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(factionID);
+ Push(standing);
+ Push(incremental);
+ int standingIndex = lua_gettop(L) - 1;
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_REPUTATION_CHANGE, 4);
+
+ while (n > 0)
{
- if (lua_isnumber(L, i))
- standing = CHECKVAL(L, i, standing);
+ int r = CallOneFunction(n--, 4, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ standing = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(standing, standingIndex);
+ }
+
+ lua_pop(L, 1);
}
- ENDCALL();
+
+ CleanUpStack(4);
}
void Eluna::OnDuelRequest(Player* pTarget, Player* pChallenger)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_REQUEST, return);
- Push(L, pTarget);
- Push(L, pChallenger);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_REQUEST))
+ return;
+
+ LOCK_ELUNA;
+ Push(pTarget);
+ Push(pChallenger);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_REQUEST);
}
void Eluna::OnDuelStart(Player* pStarter, Player* pChallenger)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_START, return);
- Push(L, pStarter);
- Push(L, pChallenger);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_START))
+ return;
+
+ LOCK_ELUNA;
+ Push(pStarter);
+ Push(pChallenger);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_START);
}
void Eluna::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_END, return);
- Push(L, pWinner);
- Push(L, pLoser);
- Push(L, type);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_DUEL_END))
+ return;
+
+ LOCK_ELUNA;
+ Push(pWinner);
+ Push(pLoser);
+ Push(type);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_DUEL_END);
}
void Eluna::OnEmote(Player* pPlayer, uint32 emote)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_EMOTE, return);
- Push(L, pPlayer);
- Push(L, emote);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_EMOTE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(emote);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_EMOTE);
}
void Eluna::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, uint64 guid)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_TEXT_EMOTE, return);
- Push(L, pPlayer);
- Push(L, textEmote);
- Push(L, emoteNum);
- Push(L, guid);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_TEXT_EMOTE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(textEmote);
+ Push(emoteNum);
+ Push(guid);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_TEXT_EMOTE);
}
void Eluna::OnSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_SPELL_CAST, return);
- Push(L, pPlayer);
- Push(L, pSpell);
- Push(L, skipCheck);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SPELL_CAST))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pSpell);
+ Push(skipCheck);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SPELL_CAST);
}
void Eluna::OnLogin(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_LOGIN, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGIN))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGIN);
}
void Eluna::OnLogout(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_LOGOUT, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_LOGOUT))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_LOGOUT);
}
void Eluna::OnCreate(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_CREATE, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_CREATE);
}
void Eluna::OnDelete(uint32 guidlow)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_DELETE, return);
- Push(L, guidlow);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHARACTER_DELETE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guidlow);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_CHARACTER_DELETE);
}
void Eluna::OnSave(Player* pPlayer)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_SAVE, return);
- Push(L, pPlayer);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_SAVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_SAVE);
}
void Eluna::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_BIND_TO_INSTANCE, return);
- Push(L, pPlayer);
- Push(L, difficulty);
- Push(L, mapid);
- Push(L, permanent);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_BIND_TO_INSTANCE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(difficulty);
+ Push(mapid);
+ Push(permanent);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_BIND_TO_INSTANCE);
}
void Eluna::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_UPDATE_ZONE, return);
- Push(L, pPlayer);
- Push(L, newZone);
- Push(L, newArea);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_UPDATE_ZONE))
+ return;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(newZone);
+ Push(newArea);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_UPDATE_ZONE);
}
void Eluna::OnMapChanged(Player* player)
{
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_MAP_CHANGE, return);
- Push(L, player);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_MAP_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(player);
+ CallAllFunctions(PlayerEventBindings, PLAYER_EVENT_ON_MAP_CHANGE);
}
bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg)
{
if (lang == LANG_ADDON)
- {
- OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, NULL);
+ return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, NULL);
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHAT))
return true;
- }
+
+ LOCK_ELUNA;
bool result = true;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_CHAT, return result);
- Push(L, pPlayer);
- Push(L, msg);
- Push(L, type);
- Push(L, lang);
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHAT, 4);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isstring(L, i))
- {
- if (const char* c_str = CHECKVAL(L, i, NULL))
- msg = std::string(c_str);
- }
- else if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 4, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(4);
return result;
}
bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Group* pGroup)
{
if (lang == LANG_ADDON)
- {
- OnAddonMessage(pPlayer, type, msg, NULL, NULL, pGroup, NULL);
+ return OnAddonMessage(pPlayer, type, msg, NULL, NULL, pGroup, NULL);
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GROUP_CHAT))
return true;
- }
+
+ LOCK_ELUNA;
bool result = true;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_GROUP_CHAT, return result);
- Push(L, pPlayer);
- Push(L, msg);
- Push(L, type);
- Push(L, lang);
- Push(L, pGroup);
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pGroup);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GROUP_CHAT, 5);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isstring(L, i))
- {
- if (const char* c_str = CHECKVAL(L, i, NULL))
- msg = std::string(c_str);
- }
- else if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(5);
return result;
}
bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Guild* pGuild)
{
if (lang == LANG_ADDON)
- {
- OnAddonMessage(pPlayer, type, msg, NULL, pGuild, NULL, NULL);
+ return OnAddonMessage(pPlayer, type, msg, NULL, pGuild, NULL, NULL);
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_GUILD_CHAT))
return true;
- }
+
+ LOCK_ELUNA;
bool result = true;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_GUILD_CHAT, return result);
- Push(L, pPlayer);
- Push(L, msg);
- Push(L, type);
- Push(L, lang);
- Push(L, pGuild);
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pGuild);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_GUILD_CHAT, 5);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isstring(L, i))
- {
- if (const char* c_str = CHECKVAL(L, i, NULL))
- msg = std::string(c_str);
- }
- else if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(5);
return result;
}
bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Channel* pChannel)
{
if (lang == LANG_ADDON)
- {
- OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, pChannel);
+ return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, pChannel);
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_CHANNEL_CHAT))
return true;
- }
+
+ LOCK_ELUNA;
bool result = true;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_CHANNEL_CHAT, return result);
- Push(L, pPlayer);
- Push(L, msg);
- Push(L, type);
- Push(L, lang);
- Push(L, pChannel->GetChannelId());
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pChannel->GetChannelId());
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_CHANNEL_CHAT, 5);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isstring(L, i))
- {
- if (const char* c_str = CHECKVAL(L, i, NULL))
- msg = std::string(c_str);
- }
- else if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(5);
return result;
}
bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Player* pReceiver)
{
if (lang == LANG_ADDON)
- {
- OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL);
+ return OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL);
+
+ if (!PlayerEventBindings->HasEvents(PLAYER_EVENT_ON_WHISPER))
return true;
- }
+
+ LOCK_ELUNA;
bool result = true;
- EVENT_BEGIN(PlayerEventBindings, PLAYER_EVENT_ON_WHISPER, return result);
- Push(L, pPlayer);
- Push(L, msg);
- Push(L, type);
- Push(L, lang);
- Push(L, pReceiver);
- EVENT_EXECUTE(2);
- FOR_RETS(i)
+ Push(pPlayer);
+ Push(msg);
+ Push(type);
+ Push(lang);
+ Push(pReceiver);
+ int n = SetupStack(PlayerEventBindings, PLAYER_EVENT_ON_WHISPER, 5);
+
+ while (n > 0)
{
- if (lua_isnoneornil(L, i))
- continue;
- if (lua_isstring(L, i))
- {
- if (const char* c_str = CHECKVAL(L, i, NULL))
- msg = std::string(c_str);
- }
- else if (lua_isboolean(L, i) && !CHECKVAL(L, i, true))
- {
+ int r = CallOneFunction(n--, 5, 2);
+
+ if (lua_isboolean(L, r + 0) && !lua_toboolean(L, r + 0))
result = false;
- break;
- }
+
+ if (lua_isstring(L, r + 1))
+ msg = std::string(lua_tostring(L, r + 1));
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(5);
return result;
}
@@ -1085,782 +1362,808 @@ bool Eluna::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg,
// Vehicle
void Eluna::OnInstall(Vehicle* vehicle)
{
- EVENT_BEGIN(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL, return);
- Push(L, vehicle);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL);
}
void Eluna::OnUninstall(Vehicle* vehicle)
{
- EVENT_BEGIN(VehicleEventBindings, VEHICLE_EVENT_ON_UNINSTALL, return);
- Push(L, vehicle);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_UNINSTALL))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_UNINSTALL);
}
void Eluna::OnInstallAccessory(Vehicle* vehicle, Creature* accessory)
{
- EVENT_BEGIN(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL_ACCESSORY, return);
- Push(L, vehicle);
- Push(L, accessory);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_INSTALL_ACCESSORY))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ Push(accessory);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_INSTALL_ACCESSORY);
}
void Eluna::OnAddPassenger(Vehicle* vehicle, Unit* passenger, int8 seatId)
{
- EVENT_BEGIN(VehicleEventBindings, VEHICLE_EVENT_ON_ADD_PASSENGER, return);
- Push(L, vehicle);
- Push(L, passenger);
- Push(L, seatId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_ADD_PASSENGER))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ Push(passenger);
+ Push(seatId);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_ADD_PASSENGER);
}
void Eluna::OnRemovePassenger(Vehicle* vehicle, Unit* passenger)
{
- EVENT_BEGIN(VehicleEventBindings, VEHICLE_EVENT_ON_REMOVE_PASSENGER, return);
- Push(L, vehicle);
- Push(L, passenger);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!VehicleEventBindings->HasEvents(VEHICLE_EVENT_ON_REMOVE_PASSENGER))
+ return;
+
+ LOCK_ELUNA;
+ Push(vehicle);
+ Push(passenger);
+ CallAllFunctions(VehicleEventBindings, VEHICLE_EVENT_ON_REMOVE_PASSENGER);
}
#endif
#endif
void Eluna::OnAddMember(Guild* guild, Player* player, uint32 plRank)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_ADD_MEMBER, return);
- Push(L, guild);
- Push(L, player);
- Push(L, plRank);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_ADD_MEMBER))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(plRank);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ADD_MEMBER);
}
void Eluna::OnRemoveMember(Guild* guild, Player* player, bool isDisbanding)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_REMOVE_MEMBER, return);
- Push(L, guild);
- Push(L, player);
- Push(L, isDisbanding);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_REMOVE_MEMBER))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(isDisbanding);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_REMOVE_MEMBER);
}
void Eluna::OnMOTDChanged(Guild* guild, const std::string& newMotd)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_MOTD_CHANGE, return);
- Push(L, guild);
- Push(L, newMotd);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MOTD_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(newMotd);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_MOTD_CHANGE);
}
void Eluna::OnInfoChanged(Guild* guild, const std::string& newInfo)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_INFO_CHANGE, return);
- Push(L, guild);
- Push(L, newInfo);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_INFO_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(newInfo);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_INFO_CHANGE);
}
void Eluna::OnCreate(Guild* guild, Player* leader, const std::string& name)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_CREATE, return);
- Push(L, guild);
- Push(L, leader);
- Push(L, name);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(leader);
+ Push(name);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_CREATE);
}
void Eluna::OnDisband(Guild* guild)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_DISBAND, return);
- Push(L, guild);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_DISBAND))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_DISBAND);
}
void Eluna::OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, bool isRepair) // isRepair not a part of Mangos, implement?
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_MONEY_WITHDRAW, return);
- Push(L, guild);
- Push(L, player);
- Push(L, amount);
- Push(L, isRepair); // isRepair not a part of Mangos, implement?
- EVENT_EXECUTE(1);
- FOR_RETS(i)
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MONEY_WITHDRAW))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(amount);
+ Push(isRepair); // isRepair not a part of Mangos, implement?
+ int amountIndex = lua_gettop(L) - 1;
+ int n = SetupStack(GuildEventBindings, GUILD_EVENT_ON_MONEY_WITHDRAW, 4);
+
+ while (n > 0)
{
- if (lua_isnumber(L, i))
- amount = CHECKVAL(L, i, amount);
+ int r = CallOneFunction(n--, 4, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
}
- ENDCALL();
+
+ CleanUpStack(4);
}
void Eluna::OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_MONEY_DEPOSIT, return);
- Push(L, guild);
- Push(L, player);
- Push(L, amount);
- EVENT_EXECUTE(1);
- FOR_RETS(i)
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_MONEY_DEPOSIT))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(amount);
+ int amountIndex = lua_gettop(L);
+ int n = SetupStack(GuildEventBindings, GUILD_EVENT_ON_MONEY_DEPOSIT, 3);
+
+ while (n > 0)
{
- if (lua_isnumber(L, i))
- amount = CHECKVAL(L, i, amount);
+ int r = CallOneFunction(n--, 3, 1);
+
+ if (lua_isnumber(L, r))
+ {
+ amount = CHECKVAL(L, r);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(amount, amountIndex);
+ }
+
+ lua_pop(L, 1);
}
- ENDCALL();
+
+ CleanUpStack(3);
}
void Eluna::OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
bool isDestBank, uint8 destContainer, uint8 destSlotId)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_ITEM_MOVE, return);
- Push(L, guild);
- Push(L, player);
- Push(L, pItem);
- Push(L, isSrcBank);
- Push(L, srcContainer);
- Push(L, srcSlotId);
- Push(L, isDestBank);
- Push(L, destContainer);
- Push(L, destSlotId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_ITEM_MOVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(player);
+ Push(pItem);
+ Push(isSrcBank);
+ Push(srcContainer);
+ Push(srcSlotId);
+ Push(isDestBank);
+ Push(destContainer);
+ Push(destSlotId);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_ITEM_MOVE);
}
void Eluna::OnEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_EVENT, return);
- Push(L, guild);
- Push(L, eventType);
- Push(L, playerGuid1);
- Push(L, playerGuid2);
- Push(L, newRank);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_EVENT))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(eventType);
+ Push(playerGuid1);
+ Push(playerGuid2);
+ Push(newRank);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_EVENT);
}
void Eluna::OnBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
{
- EVENT_BEGIN(GuildEventBindings, GUILD_EVENT_ON_BANK_EVENT, return);
- Push(L, guild);
- Push(L, eventType);
- Push(L, tabId);
- Push(L, playerGuid);
- Push(L, itemOrMoney);
- Push(L, itemStackCount);
- Push(L, destTabId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GuildEventBindings->HasEvents(GUILD_EVENT_ON_BANK_EVENT))
+ return;
+
+ LOCK_ELUNA;
+ Push(guild);
+ Push(eventType);
+ Push(tabId);
+ Push(playerGuid);
+ Push(itemOrMoney);
+ Push(itemStackCount);
+ Push(destTabId);
+ CallAllFunctions(GuildEventBindings, GUILD_EVENT_ON_BANK_EVENT);
}
// Group
void Eluna::OnAddMember(Group* group, uint64 guid)
{
- EVENT_BEGIN(GroupEventBindings, GROUP_EVENT_ON_MEMBER_ADD, return);
- Push(L, group);
- Push(L, guid);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_ADD))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(guid);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_ADD);
}
void Eluna::OnInviteMember(Group* group, uint64 guid)
{
- EVENT_BEGIN(GroupEventBindings, GROUP_EVENT_ON_MEMBER_INVITE, return);
- Push(L, group);
- Push(L, guid);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_INVITE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(guid);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_INVITE);
}
void Eluna::OnRemoveMember(Group* group, uint64 guid, uint8 method)
{
- EVENT_BEGIN(GroupEventBindings, GROUP_EVENT_ON_MEMBER_REMOVE, return);
- Push(L, group);
- Push(L, guid);
- Push(L, method);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_MEMBER_REMOVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(guid);
+ Push(method);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_MEMBER_REMOVE);
}
void Eluna::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
{
- EVENT_BEGIN(GroupEventBindings, GROUP_EVENT_ON_LEADER_CHANGE, return);
- Push(L, group);
- Push(L, newLeaderGuid);
- Push(L, oldLeaderGuid);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_LEADER_CHANGE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(newLeaderGuid);
+ Push(oldLeaderGuid);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_LEADER_CHANGE);
}
void Eluna::OnDisband(Group* group)
{
- EVENT_BEGIN(GroupEventBindings, GROUP_EVENT_ON_DISBAND, return);
- Push(L, group);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_DISBAND))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_DISBAND);
}
void Eluna::OnCreate(Group* group, uint64 leaderGuid, GroupType groupType)
{
- EVENT_BEGIN(GroupEventBindings, GROUP_EVENT_ON_CREATE, return);
- Push(L, group);
- Push(L, leaderGuid);
- Push(L, groupType);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!GroupEventBindings->HasEvents(GROUP_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(group);
+ Push(leaderGuid);
+ Push(groupType);
+ CallAllFunctions(GroupEventBindings, GROUP_EVENT_ON_CREATE);
}
/* Map */
void Eluna::OnCreate(Map* map)
{
- EVENT_BEGIN(ServerEventBindings, MAP_EVENT_ON_CREATE, return);
- Push(L, map);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_CREATE);
}
void Eluna::OnDestroy(Map* map)
{
- EVENT_BEGIN(ServerEventBindings, MAP_EVENT_ON_DESTROY, return);
- Push(L, map);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_DESTROY))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_DESTROY);
}
void Eluna::OnPlayerEnter(Map* map, Player* player)
{
- EVENT_BEGIN(ServerEventBindings, MAP_EVENT_ON_PLAYER_ENTER, return);
- Push(L, map);
- Push(L, player);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_ENTER))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ Push(player);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_ENTER);
}
void Eluna::OnPlayerLeave(Map* map, Player* player)
{
- EVENT_BEGIN(ServerEventBindings, MAP_EVENT_ON_PLAYER_LEAVE, return);
- Push(L, map);
- Push(L, player);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_PLAYER_LEAVE))
+ return;
+
+ LOCK_ELUNA;
+ Push(map);
+ Push(player);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_PLAYER_LEAVE);
}
void Eluna::OnUpdate(Map* map, uint32 diff)
{
+ if (!ServerEventBindings->HasEvents(MAP_EVENT_ON_UPDATE))
+ return;
+
+ LOCK_ELUNA;
// enable this for multithread
// eventMgr->globalProcessor->Update(diff);
- EVENT_BEGIN(ServerEventBindings, MAP_EVENT_ON_UPDATE, return);
- Push(L, map);
- Push(L, diff);
- EVENT_EXECUTE(0);
- ENDCALL();
+ Push(map);
+ Push(diff);
+ CallAllFunctions(ServerEventBindings, MAP_EVENT_ON_UPDATE);
}
void Eluna::OnRemove(GameObject* gameobject)
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_DELETE_GAMEOBJECT, return);
- Push(L, gameobject);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_GAMEOBJECT))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_GAMEOBJECT);
}
void Eluna::OnRemove(Creature* creature)
{
- EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_DELETE_CREATURE, return);
- Push(L, creature);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!ServerEventBindings->HasEvents(WORLD_EVENT_ON_DELETE_CREATURE))
+ return;
+
+ LOCK_ELUNA;
+ Push(creature);
+ CallAllFunctions(ServerEventBindings, WORLD_EVENT_ON_DELETE_CREATURE);
}
// creature
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, Creature* pTarget)
{
- ENTRY_BEGIN(CreatureEventBindings, pTarget->GetEntry(), CREATURE_EVENT_ON_DUMMY_EFFECT, return false);
- Push(L, pCaster);
- Push(L, spellId);
- Push(L, effIndex);
- Push(L, pTarget);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pCaster);
+ Push(spellId);
+ Push(effIndex);
+ Push(pTarget);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
}
bool Eluna::OnGossipHello(Player* pPlayer, Creature* pCreature)
{
- ENTRY_BEGIN(CreatureGossipBindings, pCreature->GetEntry(), GOSSIP_EVENT_ON_HELLO, return false);
+ if (!CreatureGossipBindings->HasEvents(GOSSIP_EVENT_ON_HELLO, pCreature->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pCreature);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ Push(pPlayer);
+ Push(pCreature);
+ return CallAllFunctionsBool(CreatureGossipBindings, GOSSIP_EVENT_ON_HELLO, pCreature->GetEntry());
}
bool Eluna::OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action)
{
- ENTRY_BEGIN(CreatureGossipBindings, pCreature->GetEntry(), GOSSIP_EVENT_ON_SELECT, return false);
+ if (!CreatureGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pCreature);
- Push(L, sender);
- Push(L, action);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ Push(pPlayer);
+ Push(pCreature);
+ Push(sender);
+ Push(action);
+ return CallAllFunctionsBool(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry());
}
bool Eluna::OnGossipSelectCode(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 action, const char* code)
{
- ENTRY_BEGIN(CreatureGossipBindings, pCreature->GetEntry(), GOSSIP_EVENT_ON_SELECT, return false);
+ if (!CreatureGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pCreature);
- Push(L, sender);
- Push(L, action);
- Push(L, code);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ Push(pPlayer);
+ Push(pCreature);
+ Push(sender);
+ Push(action);
+ Push(code);
+ return CallAllFunctionsBool(CreatureGossipBindings, GOSSIP_EVENT_ON_SELECT, pCreature->GetEntry());
}
bool Eluna::OnQuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest)
{
- ENTRY_BEGIN(CreatureEventBindings, pCreature->GetEntry(), CREATURE_EVENT_ON_QUEST_ACCEPT, return false);
- Push(L, pPlayer);
- Push(L, pCreature);
- Push(L, pQuest);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pCreature);
+ Push(pQuest);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_QUEST_ACCEPT, pCreature->GetEntry());
}
bool Eluna::OnQuestReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt)
{
- ENTRY_BEGIN(CreatureEventBindings, pCreature->GetEntry(), CREATURE_EVENT_ON_QUEST_REWARD, return false);
- Push(L, pPlayer);
- Push(L, pCreature);
- Push(L, pQuest);
- Push(L, opt);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pCreature);
+ Push(pQuest);
+ Push(opt);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_QUEST_REWARD, pCreature->GetEntry());
}
uint32 Eluna::GetDialogStatus(Player* pPlayer, Creature* pCreature)
{
- ENTRY_BEGIN(CreatureEventBindings, pCreature->GetEntry(), CREATURE_EVENT_ON_DIALOG_STATUS, return 0);
- Push(L, pPlayer);
- Push(L, pCreature);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GetEntry()))
+ return DIALOG_STATUS_SCRIPTED_NO_STATUS;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pCreature);
+ CallAllFunctions(CreatureEventBindings, CREATURE_EVENT_ON_DIALOG_STATUS, pCreature->GetEntry());
return DIALOG_STATUS_SCRIPTED_NO_STATUS;
}
void Eluna::OnAddToWorld(Creature* creature)
{
- ENTRY_BEGIN(CreatureEventBindings, creature->GetEntry(), CREATURE_EVENT_ON_ADD, return);
- Push(L, creature);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_ADD, creature->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(creature);
+ CallAllFunctions(CreatureEventBindings, CREATURE_EVENT_ON_ADD, creature->GetEntry());
}
void Eluna::OnRemoveFromWorld(Creature* creature)
{
- ENTRY_BEGIN(CreatureEventBindings, creature->GetEntry(), CREATURE_EVENT_ON_REMOVE, return);
- Push(L, creature);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_REMOVE, creature->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(creature);
+ CallAllFunctions(CreatureEventBindings, CREATURE_EVENT_ON_REMOVE, creature->GetEntry());
}
bool Eluna::OnSummoned(Creature* pCreature, Unit* pSummoner)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, pCreature->GetEntry(), CREATURE_EVENT_ON_SUMMONED, return false);
- Push(L, pCreature);
- Push(L, pSummoner);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED, pCreature->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pCreature);
+ Push(pSummoner);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_SUMMONED, pCreature->GetEntry());
}
bool Eluna::UpdateAI(Creature* me, const uint32 diff)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_AIUPDATE, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, diff);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_AIUPDATE, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(diff);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_AIUPDATE, me->GetEntry());
}
//Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
//Called at creature aggro either by MoveInLOS or Attack Start
bool Eluna::EnterCombat(Creature* me, Unit* target)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_ENTER_COMBAT, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, target);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_ENTER_COMBAT, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(target);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_ENTER_COMBAT, me->GetEntry());
}
// Called at any Damage from any attacker (before damage apply)
bool Eluna::DamageTaken(Creature* me, Unit* attacker, uint32& damage)
{
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DAMAGE_TAKEN, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_DAMAGE_TAKEN, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, attacker);
- Eluna::Push(L, damage);
- ENTRY_EXECUTE(2);
- FOR_RETS(i)
+ Push(me);
+ Push(attacker);
+ Push(damage);
+ int damageIndex = lua_gettop(L);
+ int n = SetupStack(CreatureEventBindings, CREATURE_EVENT_ON_DAMAGE_TAKEN, me->GetEntry(), 3);
+
+ while (n > 0)
{
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i);
- if (lua_isnumber(L, i))
- damage = Eluna::CHECKVAL(L, i, damage);
+ int r = CallOneFunction(n--, 3, 2);
+
+ if (lua_isboolean(L, r + 0) && lua_toboolean(L, r + 0))
+ result = true;
+
+ if (lua_isnumber(L, r + 1))
+ {
+ damage = Eluna::CHECKVAL(L, r + 1);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(damage, damageIndex);
+ }
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(3);
return result;
}
//Called at creature death
bool Eluna::JustDied(Creature* me, Unit* killer)
{
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_DIED, me->GetEntry()))
+ return false;
+
On_Reset(me);
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_DIED, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, killer);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ LOCK_ELUNA;
+ Push(me);
+ Push(killer);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_DIED, me->GetEntry());
}
//Called at creature killing another unit
bool Eluna::KilledUnit(Creature* me, Unit* victim)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_TARGET_DIED, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, victim);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_TARGET_DIED, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(victim);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_TARGET_DIED, me->GetEntry());
}
// Called when the creature summon successfully other creature
bool Eluna::JustSummoned(Creature* me, Creature* summon)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, summon);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(summon);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, me->GetEntry());
}
// Called when a summoned creature is despawned
bool Eluna::SummonedCreatureDespawn(Creature* me, Creature* summon)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, summon);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(summon);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, me->GetEntry());
}
//Called at waypoint reached or PointMovement end
bool Eluna::MovementInform(Creature* me, uint32 type, uint32 id)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_REACH_WP, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, type);
- Eluna::Push(L, id);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_REACH_WP, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(type);
+ Push(id);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_REACH_WP, me->GetEntry());
}
// Called before EnterCombat even before the creature is in combat.
bool Eluna::AttackStart(Creature* me, Unit* target)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_PRE_COMBAT, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, target);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_PRE_COMBAT, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(target);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_PRE_COMBAT, me->GetEntry());
}
// Called for reaction at stopping attack at no attackers or targets
bool Eluna::EnterEvadeMode(Creature* me)
{
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_LEAVE_COMBAT, me->GetEntry()))
+ return false;
+
On_Reset(me);
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_LEAVE_COMBAT, return false);
- Eluna::Push(L, me);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ LOCK_ELUNA;
+ Push(me);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_LEAVE_COMBAT, me->GetEntry());
}
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
bool Eluna::AttackedBy(Creature* me, Unit* attacker)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_ATTACKED_AT, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, attacker);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_ATTACKED_AT, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(attacker);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_ATTACKED_AT, me->GetEntry());
}
// Called when creature is spawned or respawned (for reseting variables)
bool Eluna::JustRespawned(Creature* me)
{
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SPAWN, me->GetEntry()))
+ return false;
+
On_Reset(me);
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_SPAWN, return false);
- Eluna::Push(L, me);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ LOCK_ELUNA;
+ Push(me);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_SPAWN, me->GetEntry());
}
// Called at reaching home after evade
bool Eluna::JustReachedHome(Creature* me)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_REACH_HOME, return false);
- Eluna::Push(L, me);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_REACH_HOME, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_REACH_HOME, me->GetEntry());
}
// Called at text emote receive from player
bool Eluna::ReceiveEmote(Creature* me, Player* player, uint32 emoteId)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_RECEIVE_EMOTE, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, player);
- Eluna::Push(L, emoteId);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(player);
+ Push(emoteId);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_RECEIVE_EMOTE, me->GetEntry());
}
// called when the corpse of this creature gets removed
bool Eluna::CorpseRemoved(Creature* me, uint32& respawnDelay)
{
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_CORPSE_REMOVED, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_CORPSE_REMOVED, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, respawnDelay);
- ENTRY_EXECUTE(2);
- FOR_RETS(i)
+ Push(me);
+ Push(respawnDelay);
+ int respawnDelayIndex = lua_gettop(L);
+ int n = SetupStack(CreatureEventBindings, CREATURE_EVENT_ON_CORPSE_REMOVED, me->GetEntry(), 2);
+
+ while (n > 0)
{
- if (lua_isboolean(L, i))
- result = Eluna::CHECKVAL(L, i);
- if (lua_isnumber(L, i))
- respawnDelay = Eluna::CHECKVAL(L, i, respawnDelay);
+ int r = CallOneFunction(n--, 2, 2);
+
+ if (lua_isboolean(L, r + 0) && lua_toboolean(L, r + 0))
+ result = true;
+
+ if (lua_isnumber(L, r + 1))
+ {
+ respawnDelay = Eluna::CHECKVAL(L, r + 1);
+ // Update the stack for subsequent calls.
+ ReplaceArgument(respawnDelay, respawnDelayIndex);
+ }
+
+ lua_pop(L, 2);
}
- ENDCALL();
+
+ CleanUpStack(2);
return result;
}
bool Eluna::MoveInLineOfSight(Creature* me, Unit* who)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_MOVE_IN_LOS, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, who);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_MOVE_IN_LOS, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(who);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_MOVE_IN_LOS, me->GetEntry());
}
// Called on creature initial spawn, respawn, death, evade (leave combat)
void Eluna::On_Reset(Creature* me) // Not an override, custom
{
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_RESET, return);
- Eluna::Push(L, me);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_RESET, me->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(me);
+ CallAllFunctions(CreatureEventBindings, CREATURE_EVENT_ON_RESET, me->GetEntry());
}
// Called when hit by a spell
bool Eluna::SpellHit(Creature* me, Unit* caster, SpellInfo const* spell)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_HIT_BY_SPELL, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, caster);
- Eluna::Push(L, spell->Id); // Pass spell object?
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_HIT_BY_SPELL, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(caster);
+ Push(spell->Id); // Pass spell object?
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_HIT_BY_SPELL, me->GetEntry());
}
// Called when spell hits a target
bool Eluna::SpellHitTarget(Creature* me, Unit* target, SpellInfo const* spell)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_SPELL_HIT_TARGET, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, target);
- Eluna::Push(L, spell->Id); // Pass spell object?
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SPELL_HIT_TARGET, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(target);
+ Push(spell->Id); // Pass spell object?
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_SPELL_HIT_TARGET, me->GetEntry());
}
#ifdef TRINITY
bool Eluna::SummonedCreatureDies(Creature* me, Creature* summon, Unit* killer)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, summon);
- Eluna::Push(L, killer);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(summon);
+ Push(killer);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, me->GetEntry());
}
// Called when owner takes damage
bool Eluna::OwnerAttackedBy(Creature* me, Unit* attacker)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_OWNER_ATTACKED_AT, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, attacker);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(attacker);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_OWNER_ATTACKED_AT, me->GetEntry());
}
// Called when owner attacks something
bool Eluna::OwnerAttacked(Creature* me, Unit* target)
{
- bool result = false;
- ENTRY_BEGIN(CreatureEventBindings, me->GetEntry(), CREATURE_EVENT_ON_OWNER_ATTACKED, return false);
- Eluna::Push(L, me);
- Eluna::Push(L, target);
- ENTRY_EXECUTE(1);
- FOR_RETS(i)
- {
- if (lua_isboolean(L, i))
- result = CHECKVAL(L, i, false);
- }
- ENDCALL();
- return result;
+ if (!CreatureEventBindings->HasEvents(CREATURE_EVENT_ON_OWNER_ATTACKED, me->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(me);
+ Push(target);
+ return CallAllFunctionsBool(CreatureEventBindings, CREATURE_EVENT_ON_OWNER_ATTACKED, me->GetEntry());
}
#endif
@@ -2060,94 +2363,104 @@ struct ElunaCreatureAI : ScriptedAI
// gameobject
bool Eluna::OnDummyEffect(Unit* pCaster, uint32 spellId, SpellEffIndex effIndex, GameObject* pTarget)
{
- ENTRY_BEGIN(GameObjectEventBindings, pTarget->GetEntry(), GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, return false);
- Push(L, pCaster);
- Push(L, spellId);
- Push(L, effIndex);
- Push(L, pTarget);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pCaster);
+ Push(spellId);
+ Push(effIndex);
+ Push(pTarget);
+ return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, pTarget->GetEntry());
}
bool Eluna::OnGossipHello(Player* pPlayer, GameObject* pGameObject)
{
- ENTRY_BEGIN(GameObjectGossipBindings, pGameObject->GetEntry(), GOSSIP_EVENT_ON_HELLO, return false);
+ if (!GameObjectGossipBindings->HasEvents(GOSSIP_EVENT_ON_HELLO, pGameObject->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pGameObject);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ Push(pPlayer);
+ Push(pGameObject);
+ return CallAllFunctionsBool(GameObjectGossipBindings, GOSSIP_EVENT_ON_HELLO, pGameObject->GetEntry());
}
bool Eluna::OnGossipSelect(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action)
{
- ENTRY_BEGIN(GameObjectGossipBindings, pGameObject->GetEntry(), GOSSIP_EVENT_ON_SELECT, return false);
+ if (!GameObjectGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pGameObject);
- Push(L, sender);
- Push(L, action);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ Push(pPlayer);
+ Push(pGameObject);
+ Push(sender);
+ Push(action);
+ return CallAllFunctionsBool(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry());
}
bool Eluna::OnGossipSelectCode(Player* pPlayer, GameObject* pGameObject, uint32 sender, uint32 action, const char* code)
{
- ENTRY_BEGIN(GameObjectGossipBindings, pGameObject->GetEntry(), GOSSIP_EVENT_ON_SELECT, return false);
+ if (!GameObjectGossipBindings->HasEvents(GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
pPlayer->PlayerTalkClass->ClearMenus();
- Push(L, pPlayer);
- Push(L, pGameObject);
- Push(L, sender);
- Push(L, action);
- Push(L, code);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ Push(pPlayer);
+ Push(pGameObject);
+ Push(sender);
+ Push(action);
+ Push(code);
+ return CallAllFunctionsBool(GameObjectGossipBindings, GOSSIP_EVENT_ON_SELECT, pGameObject->GetEntry());
}
bool Eluna::OnQuestAccept(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, return false);
- Push(L, pPlayer);
- Push(L, pGameObject);
- Push(L, pQuest);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, pGameObject->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pGameObject);
+ Push(pQuest);
+ return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, pGameObject->GetEntry());
}
void Eluna::UpdateAI(GameObject* pGameObject, uint32 diff)
{
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
pGameObject->elunaEvents->Update(diff);
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_AIUPDATE, return);
- Push(L, pGameObject);
- Push(L, diff);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ Push(pGameObject);
+ Push(diff);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_AIUPDATE, pGameObject->GetEntry());
}
bool Eluna::OnQuestReward(Player* pPlayer, GameObject* pGameObject, Quest const* pQuest, uint32 opt)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_QUEST_REWARD, return false);
- Push(L, pPlayer);
- Push(L, pGameObject);
- Push(L, pQuest);
- Push(L, opt);
- ENTRY_EXECUTE(0);
- ENDCALL();
- return true;
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry()))
+ return false;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pGameObject);
+ Push(pQuest);
+ Push(opt);
+ return CallAllFunctionsBool(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_QUEST_REWARD, pGameObject->GetEntry());
}
uint32 Eluna::GetDialogStatus(Player* pPlayer, GameObject* pGameObject)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_DIALOG_STATUS, return 0);
- Push(L, pPlayer);
- Push(L, pGameObject);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry()))
+ return DIALOG_STATUS_SCRIPTED_NO_STATUS;
+
+ LOCK_ELUNA;
+ Push(pPlayer);
+ Push(pGameObject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DIALOG_STATUS, pGameObject->GetEntry());
return DIALOG_STATUS_SCRIPTED_NO_STATUS; // DIALOG_STATUS_UNDEFINED
}
@@ -2155,64 +2468,78 @@ uint32 Eluna::GetDialogStatus(Player* pPlayer, GameObject* pGameObject)
#ifndef TBC
void Eluna::OnDestroyed(GameObject* pGameObject, Player* pPlayer)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_DESTROYED, return);
- Push(L, pGameObject);
- Push(L, pPlayer);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(pPlayer);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DESTROYED, pGameObject->GetEntry());
}
void Eluna::OnDamaged(GameObject* pGameObject, Player* pPlayer)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_DAMAGED, return);
- Push(L, pGameObject);
- Push(L, pPlayer);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(pPlayer);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_DAMAGED, pGameObject->GetEntry());
}
#endif
#endif
void Eluna::OnLootStateChanged(GameObject* pGameObject, uint32 state)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, return);
- Push(L, pGameObject);
- Push(L, state);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(state);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, pGameObject->GetEntry());
}
void Eluna::OnGameObjectStateChanged(GameObject* pGameObject, uint32 state)
{
- ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, return);
- Push(L, pGameObject);
- Push(L, state);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(pGameObject);
+ Push(state);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, pGameObject->GetEntry());
}
void Eluna::OnSpawn(GameObject* gameobject)
{
- ENTRY_BEGIN(GameObjectEventBindings, gameobject->GetEntry(), GAMEOBJECT_EVENT_ON_SPAWN, return);
- Push(L, gameobject);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_SPAWN, gameobject->GetEntry());
}
void Eluna::OnAddToWorld(GameObject* gameobject)
{
- ENTRY_BEGIN(GameObjectEventBindings, gameobject->GetEntry(), GAMEOBJECT_EVENT_ON_ADD, return);
- Push(L, gameobject);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_ADD, gameobject->GetEntry());
}
void Eluna::OnRemoveFromWorld(GameObject* gameobject)
{
- ENTRY_BEGIN(GameObjectEventBindings, gameobject->GetEntry(), GAMEOBJECT_EVENT_ON_REMOVE, return);
- Push(L, gameobject);
- ENTRY_EXECUTE(0);
- ENDCALL();
+ if (!GameObjectEventBindings->HasEvents(GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry()))
+ return;
+
+ LOCK_ELUNA;
+ Push(gameobject);
+ CallAllFunctions(GameObjectEventBindings, GAMEOBJECT_EVENT_ON_REMOVE, gameobject->GetEntry());
}
CreatureAI* Eluna::GetAI(Creature* creature)
@@ -2224,41 +2551,49 @@ CreatureAI* Eluna::GetAI(Creature* creature)
void Eluna::OnBGStart(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
{
- EVENT_BEGIN(BGEventBindings, BG_EVENT_ON_START, return);
- Push(L, bg);
- Push(L, bgId);
- Push(L, instanceId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_START))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_START);
}
void Eluna::OnBGEnd(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId, Team winner)
{
- EVENT_BEGIN(BGEventBindings, BG_EVENT_ON_END, return);
- Push(L, bg);
- Push(L, bgId);
- Push(L, instanceId);
- Push(L, winner);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_END))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ Push(winner);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_END);
}
void Eluna::OnBGCreate(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
{
- EVENT_BEGIN(BGEventBindings, BG_EVENT_ON_CREATE, return);
- Push(L, bg);
- Push(L, bgId);
- Push(L, instanceId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_CREATE))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_CREATE);
}
void Eluna::OnBGDestroy(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId)
{
- EVENT_BEGIN(BGEventBindings, BG_EVENT_ON_PRE_DESTROY, return);
- Push(L, bg);
- Push(L, bgId);
- Push(L, instanceId);
- EVENT_EXECUTE(0);
- ENDCALL();
+ if (!BGEventBindings->HasEvents(BG_EVENT_ON_PRE_DESTROY))
+ return;
+
+ LOCK_ELUNA;
+ Push(bg);
+ Push(bgId);
+ Push(instanceId);
+ CallAllFunctions(BGEventBindings, BG_EVENT_ON_PRE_DESTROY);
}
diff --git a/LuaEngine.cpp b/LuaEngine.cpp
index 36195af..29a7f9b 100644
--- a/LuaEngine.cpp
+++ b/LuaEngine.cpp
@@ -36,6 +36,7 @@ std::string Eluna::lua_requirepath;
Eluna* Eluna::GEluna = NULL;
bool Eluna::reload = false;
bool Eluna::initialized = false;
+Eluna::LockType Eluna::lock;
extern void RegisterFunctions(Eluna* E);
@@ -88,13 +89,13 @@ void Eluna::ReloadEluna()
EventMgr::ProcessorSet oldProcessors;
{
- EventMgr::ReadGuard lock(sEluna->eventMgr->GetLock());
+ EventMgr::ReadGuard guard(sEluna->eventMgr->GetLock());
oldProcessors = sEluna->eventMgr->processors;
}
Uninitialize();
Initialize();
{
- EventMgr::WriteGuard lock(sEluna->eventMgr->GetLock());
+ EventMgr::WriteGuard guard(sEluna->eventMgr->GetLock());
sEluna->eventMgr->processors.insert(oldProcessors.begin(), oldProcessors.end());
}
@@ -118,6 +119,7 @@ Eluna::Eluna() :
L(luaL_newstate()),
event_level(0),
+push_counter(0),
eventMgr(NULL),
@@ -431,19 +433,31 @@ void Eluna::report(lua_State* luastate)
void Eluna::ExecuteCall(int params, int res)
{
int top = lua_gettop(L);
- int type = lua_type(L, top - params);
+ // Expected: function, [parameters]
+ ASSERT(top > params);
+
+ // Check function type
+ int type = lua_type(L, top - params);
if (type != LUA_TFUNCTION)
{
- lua_pop(L, params + 1); // Cleanup the stack.
ELUNA_LOG_ERROR("[Eluna]: Cannot execute call: registered value is %s, not a function.", lua_typename(L, type));
- return;
+ ASSERT(false);
}
+ // Objects are invalidated when event level hits 0
++event_level;
- if (lua_pcall(L, params, res, 0))
- report(L);
+ int result = lua_pcall(L, params, res, 0);
--event_level;
+
+ // lua_pcall returns 0 on success.
+ // On error we report errors and push nils for expected amount of returned values
+ if (result)
+ {
+ report(L);
+ for (int i = 0; i < res; ++i)
+ lua_pushnil(L);
+ }
}
void Eluna::Push(lua_State* luastate)
diff --git a/LuaEngine.h b/LuaEngine.h
index 77d40d7..2b3ef7f 100644
--- a/LuaEngine.h
+++ b/LuaEngine.h
@@ -109,6 +109,44 @@ private:
Eluna(Eluna const&);
Eluna& operator=(const Eluna&);
+ // Some helpers for hooks to call event handlers.
+ template int SetupStack(EventBind* event_bindings, EntryBind* entry_bindings, T event_id, uint32 entry, int number_of_arguments);
+ void CleanUpStack(int number_of_arguments);
+ template void ReplaceArgument(T value, uint8 index);
+ int CallOneFunction(int number_of_functions, int number_of_arguments, int number_of_results);
+ template void CallAllFunctions(EventBind* event_bindings, EntryBind* entry_bindings, T event_id, uint32 entry);
+ template bool CallAllFunctionsBool(EventBind* event_bindings, EntryBind* entry_bindings, T event_id, uint32 entry, bool default_value);
+
+ // Convenient overloads for Setup. Use these in hooks instead of original.
+ template int SetupStack(EventBind* event_bindings, T event_id, int number_of_arguments)
+ {
+ return SetupStack(event_bindings, (EntryBind*)NULL, event_id, 0, number_of_arguments);
+ }
+ template int SetupStack(EntryBind* entry_bindings, T event_id, uint32 entry, int number_of_arguments)
+ {
+ return SetupStack((EventBind*)NULL, entry_bindings, event_id, entry, number_of_arguments);
+ }
+
+ // Convenient overloads for CallAllFunctions. Use these in hooks instead of original.
+ template void CallAllFunctions(EventBind* event_bindings, T event_id)
+ {
+ CallAllFunctions(event_bindings, (EntryBind*)NULL, event_id, 0);
+ }
+ template void CallAllFunctions(EntryBind* entry_bindings, T event_id, uint32 entry)
+ {
+ CallAllFunctions((EventBind*)NULL, entry_bindings, event_id, entry);
+ }
+
+ // Convenient overloads for CallAllFunctionsBool. Use these in hooks instead of original.
+ template bool CallAllFunctionsBool(EventBind* event_bindings, T event_id, bool default_value = false)
+ {
+ return CallAllFunctionsBool(event_bindings, (EntryBind*)NULL, event_id, 0, default_value);
+ }
+ template bool CallAllFunctionsBool(EntryBind* entry_bindings, T event_id, uint32 entry, bool default_value = false)
+ {
+ return CallAllFunctionsBool((EventBind*)NULL, entry_bindings, event_id, entry, default_value);
+ }
+
public:
typedef std::list ScriptList;
@@ -118,13 +156,13 @@ public:
#ifdef TRINITY
typedef std::recursive_mutex LockType;
- typedef std::lock_guard ElunaGuard;
+ typedef std::lock_guard Guard;
#else
typedef ACE_Recursive_Thread_Mutex LockType;
- typedef ACE_Guard ElunaGuard;
+ typedef ACE_Guard Guard;
#endif
- LockType elunaLock;
+ static LockType lock;
lua_State* L;
uint32 event_level;
@@ -168,7 +206,7 @@ public:
void RunScripts();
void InvalidateObjects();
- // Pushes
+ // Static pushes, can be used by anything, including methods.
static void Push(lua_State* luastate); // nil
static void Push(lua_State* luastate, const long long);
static void Push(lua_State* luastate, const unsigned long long);
@@ -191,6 +229,26 @@ public:
static void Push(lua_State* luastate, Pet const* pet);
static void Push(lua_State* luastate, TempSummon const* summon);
+ // When a hook pushes arguments to be passed to event handlers
+ // this is used to keep track of how many arguments were pushed.
+ uint8 push_counter;
+
+ // Non-static pushes, to be used in hooks.
+ // These just call the correct static version with the main thread's Lua state.
+ void Push() { Push(L); ++push_counter; }
+ void Push(const long long value) { Push(L, value); ++push_counter; }
+ void Push(const unsigned long long value) { Push(L, value); ++push_counter; }
+ void Push(const long value) { Push(L, value); ++push_counter; }
+ void Push(const unsigned long value) { Push(L, value); ++push_counter; }
+ void Push(const int value) { Push(L, value); ++push_counter; }
+ void Push(const unsigned int value) { Push(L, value); ++push_counter; }
+ void Push(const bool value) { Push(L, value); ++push_counter; }
+ void Push(const float value) { Push(L, value); ++push_counter; }
+ void Push(const double value) { Push(L, value); ++push_counter; }
+ void Push(const std::string& value) { Push(L, value); ++push_counter; }
+ void Push(const char* value) { Push(L, value); ++push_counter; }
+ template void Push(T const* ptr){ Push(L, ptr); ++push_counter; }
+
// Checks
template static T CHECKVAL(lua_State* luastate, int narg);
template static T CHECKVAL(lua_State* luastate, int narg, T def)
@@ -401,5 +459,5 @@ template<> WorldObject* Eluna::CHECKOBJ(lua_State* L, int narg, boo
template<> ElunaObject* Eluna::CHECKOBJ(lua_State* L, int narg, bool error);
#define sEluna Eluna::GEluna
-#define ELUNA_LOCK(E) Eluna::ElunaGuard elunaGuard((E)->elunaLock);
+#define LOCK_ELUNA Eluna::Guard __guard(Eluna::lock)
#endif