mirror of
https://github.com/azerothcore/mod-ale
synced 2025-11-29 15:38:17 +08:00
Eluna fix crash in timed events and prepare some for future changes. Ditched EventProcessor
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "ElunaEventMgr.h"
|
||||
#include "LuaEngine.h"
|
||||
#include "Object.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -13,139 +14,131 @@ extern "C"
|
||||
#include "lauxlib.h"
|
||||
};
|
||||
|
||||
LuaEvent::LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj):
|
||||
E(_E), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls), obj(_obj)
|
||||
LuaEvent::LuaEvent(ElunaEventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls) :
|
||||
to_Abort(false), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls)
|
||||
{
|
||||
if (_events)
|
||||
E.m_EventMgr->LuaEvents[_events].insert(this); // Able to access the event if we have the processor
|
||||
}
|
||||
|
||||
LuaEvent::~LuaEvent()
|
||||
{
|
||||
if (events)
|
||||
{
|
||||
// Attempt to remove the pointer from LuaEvents
|
||||
EventMgr::EventMap::const_iterator it = E.m_EventMgr->LuaEvents.find(events); // Get event set
|
||||
if (it != E.m_EventMgr->LuaEvents.end())
|
||||
E.m_EventMgr->LuaEvents[events].erase(this);// Remove pointer
|
||||
}
|
||||
luaL_unref(E.L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref
|
||||
luaL_unref(sEluna->L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref
|
||||
}
|
||||
|
||||
bool LuaEvent::Execute(uint64 /*time*/, uint32 /*diff*/)
|
||||
void LuaEvent::Execute()
|
||||
{
|
||||
bool remove = (calls == 1);
|
||||
if (!remove)
|
||||
events->AddEvent(this, events->CalculateTime(delay)); // Reschedule before calling incase RemoveEvents used
|
||||
lua_rawgeti(E.L, LUA_REGISTRYINDEX, funcRef);
|
||||
Eluna::Push(E.L, funcRef);
|
||||
Eluna::Push(E.L, delay);
|
||||
Eluna::Push(E.L, calls);
|
||||
if (!remove && calls)
|
||||
// In multithread get map from object and the map's lua state
|
||||
lua_rawgeti(sEluna->L, LUA_REGISTRYINDEX, funcRef);
|
||||
Eluna::Push(sEluna->L, funcRef);
|
||||
Eluna::Push(sEluna->L, delay);
|
||||
Eluna::Push(sEluna->L, calls);
|
||||
if (calls) // Must be before calling
|
||||
--calls;
|
||||
Eluna::Push(E.L, obj);
|
||||
Eluna::ExecuteCall(E.L, 4, 0);
|
||||
return remove; // Destory (true) event if not run
|
||||
Eluna::Push(sEluna->L, events->obj);
|
||||
Eluna::ExecuteCall(sEluna->L, 4, 0);
|
||||
}
|
||||
|
||||
EventMgr::EventMgr(Eluna& _E): E(_E)
|
||||
ElunaEventProcessor::ElunaEventProcessor(WorldObject* _obj) : m_time(0), obj(_obj)
|
||||
{
|
||||
// In multithread get the object's map's lua state
|
||||
Eluna* E = obj ? sEluna : sEluna;
|
||||
|
||||
EventMgr::WriteGuard lock(E->eventMgr->GetLock());
|
||||
E->eventMgr->processors.insert(this);
|
||||
}
|
||||
|
||||
ElunaEventProcessor::~ElunaEventProcessor()
|
||||
{
|
||||
RemoveEvents();
|
||||
|
||||
// In multithread get the object's map's lua state
|
||||
Eluna* E = obj ? sEluna : sEluna;
|
||||
EventMgr::WriteGuard lock(E->eventMgr->GetLock());
|
||||
E->eventMgr->processors.erase(this);
|
||||
}
|
||||
|
||||
void ElunaEventProcessor::Update(uint32 diff)
|
||||
{
|
||||
m_time += diff;
|
||||
for (EventList::iterator it = eventList.begin(); it != eventList.end() && it->first <= m_time; it = eventList.begin())
|
||||
{
|
||||
LuaEvent* event = it->second;
|
||||
eventList.erase(it);
|
||||
eventMap.erase(event->funcRef);
|
||||
|
||||
if (event->to_Abort)
|
||||
{
|
||||
delete event;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool remove = event->calls == 1;
|
||||
if (!remove)
|
||||
AddEvent(event); // Reschedule before calling incase RemoveEvents used
|
||||
|
||||
event->Execute();
|
||||
|
||||
if (remove)
|
||||
delete event;
|
||||
}
|
||||
}
|
||||
|
||||
void ElunaEventProcessor::RemoveEvents()
|
||||
{
|
||||
//if (!final)
|
||||
//{
|
||||
// for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it)
|
||||
// it->second->to_Abort = true;
|
||||
// return;
|
||||
//}
|
||||
|
||||
for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it)
|
||||
delete it->second;
|
||||
|
||||
eventList.clear();
|
||||
eventMap.clear();
|
||||
}
|
||||
|
||||
void ElunaEventProcessor::RemoveEvent(int eventId)
|
||||
{
|
||||
if (eventMap.find(eventId) != eventMap.end())
|
||||
eventMap[eventId]->to_Abort = true;
|
||||
}
|
||||
|
||||
void ElunaEventProcessor::AddEvent(LuaEvent* event)
|
||||
{
|
||||
eventList.insert(std::pair<uint64, LuaEvent*>(m_time + event->delay, event));
|
||||
eventMap[event->funcRef] = event;
|
||||
}
|
||||
|
||||
void ElunaEventProcessor::AddEvent(int funcRef, uint32 delay, uint32 repeats)
|
||||
{
|
||||
AddEvent(new LuaEvent(this, funcRef, delay, repeats));
|
||||
}
|
||||
|
||||
EventMgr::EventMgr() : globalProcessor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
EventMgr::~EventMgr()
|
||||
{
|
||||
RemoveEvents();
|
||||
delete globalProcessor;
|
||||
}
|
||||
|
||||
void EventMgr::Update(uint32 diff)
|
||||
{
|
||||
GlobalEvents.Update(diff);
|
||||
}
|
||||
|
||||
/*
|
||||
void EventMgr::KillAllEvents(EventProcessor* events)
|
||||
{
|
||||
if (!events)
|
||||
return;
|
||||
if (LuaEvents.empty())
|
||||
return;
|
||||
EventMap::const_iterator it = LuaEvents.find(events); // Get event set
|
||||
if (it == LuaEvents.end())
|
||||
return;
|
||||
if (it->second.empty())
|
||||
return;
|
||||
for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end();) // Loop events
|
||||
(*(itr++))->to_Abort = true; // Abort event
|
||||
}
|
||||
*/
|
||||
|
||||
void EventMgr::RemoveEvents()
|
||||
{
|
||||
if (!LuaEvents.empty())
|
||||
for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors
|
||||
(it++)->first->KillAllEvents(false); // KillAllEvents((it++)->first);
|
||||
LuaEvents.clear(); // remove pointers
|
||||
// This is handled automatically on delete
|
||||
// for (ProcessorMap::iterator it = Processors.begin(); it != Processors.end();)
|
||||
// (it++)->second.KillAllEvents(true);
|
||||
// Processors.clear(); // remove guid saved processors
|
||||
GlobalEvents.KillAllEvents(true);
|
||||
}
|
||||
|
||||
void EventMgr::RemoveEvents(EventProcessor* events)
|
||||
{
|
||||
if (!events)
|
||||
return;
|
||||
// KillAllEvents(events);
|
||||
events->KillAllEvents(false);
|
||||
LuaEvents.erase(events); // remove pointer set
|
||||
}
|
||||
|
||||
int EventMgr::AddEvent(EventProcessor* events, int funcRef, uint32 delay, uint32 calls, Object* obj)
|
||||
{
|
||||
if (!events || funcRef <= 0) // If funcRef <= 0, function reference failed
|
||||
return 0; // on fail always return 0. funcRef can be negative.
|
||||
events->AddEvent(new LuaEvent(E, events, funcRef, delay, calls, obj), events->CalculateTime(delay));
|
||||
return funcRef; // return the event ID
|
||||
}
|
||||
|
||||
LuaEvent* EventMgr::GetEvent(EventProcessor* events, int eventId)
|
||||
{
|
||||
if (!events || !eventId)
|
||||
return NULL;
|
||||
if (LuaEvents.empty())
|
||||
return NULL;
|
||||
EventMap::const_iterator it = LuaEvents.find(events); // Get event set
|
||||
if (it == LuaEvents.end())
|
||||
return NULL;
|
||||
if (it->second.empty())
|
||||
return NULL;
|
||||
for (EventSet::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr) // Loop events
|
||||
if ((*itr) && (*itr)->funcRef == eventId) // Check if the event has our ID
|
||||
return *itr; // Return the event if found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool EventMgr::RemoveEvent(EventProcessor* events, int eventId)
|
||||
{
|
||||
// eventId = funcRef
|
||||
if (!events || !eventId)
|
||||
return false;
|
||||
LuaEvent* luaEvent = GetEvent(events, eventId);
|
||||
if (!luaEvent)
|
||||
return false;
|
||||
luaEvent->to_Abort = true; // Set to remove on next call
|
||||
LuaEvents[events].erase(luaEvent); // Remove pointer
|
||||
return true;
|
||||
ReadGuard lock(GetLock());
|
||||
if (!processors.empty())
|
||||
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
|
||||
(*it)->RemoveEvents();
|
||||
globalProcessor->RemoveEvents();
|
||||
}
|
||||
|
||||
void EventMgr::RemoveEvent(int eventId)
|
||||
{
|
||||
if (!eventId)
|
||||
return;
|
||||
if (LuaEvents.empty())
|
||||
return;
|
||||
for (EventMap::const_iterator it = LuaEvents.begin(); it != LuaEvents.end();) // loop processors
|
||||
if (RemoveEvent((it++)->first, eventId))
|
||||
break; // succesfully remove the event, stop loop.
|
||||
ReadGuard lock(GetLock());
|
||||
if (!processors.empty())
|
||||
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
|
||||
(*it)->RemoveEvent(eventId);
|
||||
globalProcessor->RemoveEvent(eventId);
|
||||
}
|
||||
|
||||
@@ -7,75 +7,82 @@
|
||||
#ifndef _ELUNA_EVENT_MGR_H
|
||||
#define _ELUNA_EVENT_MGR_H
|
||||
|
||||
#include "ElunaUtility.h"
|
||||
#include "Common.h"
|
||||
#include <map>
|
||||
|
||||
#ifdef TRINITY
|
||||
#include "EventProcessor.h"
|
||||
#include "Define.h"
|
||||
#else
|
||||
#include "Utilities/EventProcessor.h"
|
||||
#include "Platform/Define.h"
|
||||
#endif
|
||||
|
||||
class Eluna;
|
||||
class EventMgr;
|
||||
class EventProcessor;
|
||||
class Object;
|
||||
class ElunaEventProcessor;
|
||||
class WorldObject;
|
||||
|
||||
class LuaEvent : public BasicEvent
|
||||
class LuaEvent
|
||||
{
|
||||
friend class EventMgr;
|
||||
friend class ElunaEventProcessor;
|
||||
|
||||
public:
|
||||
LuaEvent(Eluna& _E, EventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls, Object* _obj);
|
||||
~LuaEvent();
|
||||
|
||||
// Should never execute on dead events
|
||||
bool Execute(uint64 time, uint32 diff);
|
||||
void Execute();
|
||||
bool to_Abort;
|
||||
|
||||
private:
|
||||
Eluna& E;
|
||||
EventProcessor* events; // Pointer to events (holds the timed event)
|
||||
LuaEvent(ElunaEventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls);
|
||||
~LuaEvent();
|
||||
|
||||
ElunaEventProcessor* events; // Pointer to events (holds the timed event)
|
||||
int funcRef; // Lua function reference ID, also used as event ID
|
||||
uint32 delay; // Delay between event calls
|
||||
uint32 calls; // Amount of calls to make, 0 for infinite
|
||||
Object* obj; // Object to push
|
||||
};
|
||||
|
||||
class EventMgr
|
||||
class ElunaEventProcessor
|
||||
{
|
||||
friend class LuaEvent;
|
||||
|
||||
public:
|
||||
typedef std::multimap<uint64, LuaEvent*> EventList;
|
||||
typedef UNORDERED_MAP<int, LuaEvent*> EventMap;
|
||||
|
||||
ElunaEventProcessor(WorldObject* _obj);
|
||||
~ElunaEventProcessor();
|
||||
|
||||
void Update(uint32 diff);
|
||||
// instantly removes all timed events
|
||||
void RemoveEvents();
|
||||
// set the event to be removed when executing
|
||||
void RemoveEvent(int eventId);
|
||||
void AddEvent(int funcRef, uint32 delay, uint32 repeats);
|
||||
EventMap eventMap;
|
||||
|
||||
private:
|
||||
void AddEvent(LuaEvent* Event);
|
||||
EventList eventList;
|
||||
uint64 m_time;
|
||||
WorldObject* obj;
|
||||
};
|
||||
|
||||
class EventMgr : public ElunaUtil::RWLockable
|
||||
{
|
||||
public:
|
||||
typedef std::set<LuaEvent*> EventSet;
|
||||
typedef std::map<EventProcessor*, EventSet> EventMap;
|
||||
Eluna& E;
|
||||
typedef UNORDERED_SET<ElunaEventProcessor*> ProcessorSet;
|
||||
ProcessorSet processors;
|
||||
ElunaEventProcessor* globalProcessor;
|
||||
|
||||
EventMap LuaEvents; // LuaEvents[processor] = {LuaEvent, LuaEvent...}
|
||||
EventProcessor GlobalEvents;
|
||||
|
||||
EventMgr(Eluna& _E);
|
||||
EventMgr();
|
||||
~EventMgr();
|
||||
|
||||
// Should be run on world tick
|
||||
void Update(uint32 diff);
|
||||
|
||||
// Aborts all lua events
|
||||
// void KillAllEvents(EventProcessor* events);
|
||||
|
||||
// Remove all timed events
|
||||
// Execute only in safe env
|
||||
void RemoveEvents();
|
||||
|
||||
// Remove timed events from processor
|
||||
void RemoveEvents(EventProcessor* events);
|
||||
|
||||
// Adds a new event to the processor and returns the eventID or 0 (Never negative)
|
||||
int AddEvent(EventProcessor* events, int funcRef, uint32 delay, uint32 calls, Object* obj = NULL);
|
||||
|
||||
// Finds the event that has the ID from events
|
||||
LuaEvent* GetEvent(EventProcessor* events, int eventId);
|
||||
|
||||
// Remove the event with the eventId from processor
|
||||
// Returns true if event is removed
|
||||
// EventId is func ref
|
||||
bool RemoveEvent(EventProcessor* events, int eventId);
|
||||
|
||||
// Removes the eventId from all events
|
||||
// Execute only in safe env
|
||||
void RemoveEvent(int eventId);
|
||||
};
|
||||
|
||||
|
||||
@@ -120,3 +120,9 @@ enum SelectAggroTarget
|
||||
SELECT_TARGET_FARTHEST
|
||||
};
|
||||
#endif
|
||||
|
||||
// Some dummy includes containing BOOST_VERSION:
|
||||
// ObjectAccessor.h Config.h Log.h
|
||||
#ifdef BOOST_VERSION
|
||||
#define USING_BOOST
|
||||
#endif
|
||||
|
||||
@@ -43,6 +43,9 @@ typedef uint64 ObjectGuid;
|
||||
#ifndef UNORDERED_MAP
|
||||
#define UNORDERED_MAP std::unordered_map
|
||||
#endif
|
||||
#ifndef UNORDERED_SET
|
||||
#define UNORDERED_ET std::unordered_set
|
||||
#endif
|
||||
|
||||
class Unit;
|
||||
class WorldObject;
|
||||
@@ -91,6 +94,35 @@ namespace ElunaUtil
|
||||
|
||||
WorldObjectInRangeCheck(WorldObjectInRangeCheck const&);
|
||||
};
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
* Inherit this class, then when needing lock, use
|
||||
* ReadGuard lock(_lock);
|
||||
* or
|
||||
* WriteGuard lock(_lock);
|
||||
*
|
||||
* The lock is automatically released at end of scope
|
||||
*/
|
||||
class RWLockable
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef USING_BOOST
|
||||
typedef boost::shared_mutex LockType;
|
||||
typedef boost::shared_lock<boost::shared_mutex> ReadGuard;
|
||||
typedef boost::unique_lock<boost::shared_mutex> WriteGuard;
|
||||
#else
|
||||
typedef ACE_RW_Thread_Mutex LockType;
|
||||
typedef ACE_Read_Guard<LockType> ReadGuard;
|
||||
typedef ACE_Write_Guard<LockType> WriteGuard;
|
||||
#endif
|
||||
|
||||
LockType& GetLock() { return _lock; }
|
||||
|
||||
private:
|
||||
LockType _lock;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -204,50 +204,6 @@ namespace LuaGameObject
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a timed event to the [GameObject]
|
||||
*
|
||||
* @param function function : function to trigger when the time has passed
|
||||
* @param uint32 delay : set time in milliseconds for the event to trigger
|
||||
* @param uint32 repeats : how many times for the event to repeat, 0 is infinite
|
||||
* @return int32 eventId : unique ID for the timed event used to cancel it
|
||||
*/
|
||||
int RegisterEvent(lua_State* L, GameObject* go)
|
||||
{
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
uint32 delay = Eluna::CHECKVAL<uint32>(L, 3);
|
||||
uint32 repeats = Eluna::CHECKVAL<uint32>(L, 4);
|
||||
|
||||
lua_pushvalue(L, 2);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
functionRef = sEluna->m_EventMgr->AddEvent(&go->m_Events, functionRef, delay, repeats, go);
|
||||
if (functionRef)
|
||||
Eluna::Push(L, functionRef);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the timed event from a [GameObject] by the specified event ID
|
||||
*
|
||||
* @param int32 eventId : event Id to remove
|
||||
*/
|
||||
int RemoveEventById(lua_State* L, GameObject* go)
|
||||
{
|
||||
int eventId = Eluna::CHECKVAL<int>(L, 2);
|
||||
sEluna->m_EventMgr->RemoveEvent(&go->m_Events, eventId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all timed events from a [GameObject]
|
||||
*
|
||||
*/
|
||||
int RemoveEvents(lua_State* /*L*/, GameObject* go)
|
||||
{
|
||||
sEluna->m_EventMgr->RemoveEvents(&go->m_Events);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes uses a door or a button type [GameObject]
|
||||
*
|
||||
|
||||
@@ -692,6 +692,16 @@ namespace LuaGlobalFunctions
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a global timed event
|
||||
* When the passed function is called, the parameters `(eventId, delay, repeats)` are passed to it.
|
||||
* Repeats will decrease on each call if the event does not repeat indefinitely
|
||||
*
|
||||
* @param function function : function to trigger when the time has passed
|
||||
* @param uint32 delay : set time in milliseconds for the event to trigger
|
||||
* @param uint32 repeats : how many times for the event to repeat, 0 is infinite
|
||||
* @return int eventId : unique ID for the timed event used to cancel it or nil
|
||||
*/
|
||||
int CreateLuaEvent(lua_State* L)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
@@ -700,34 +710,47 @@ namespace LuaGlobalFunctions
|
||||
|
||||
lua_pushvalue(L, 1);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
functionRef = sEluna->m_EventMgr->AddEvent(&sEluna->m_EventMgr->GlobalEvents, functionRef, delay, repeats);
|
||||
if (functionRef)
|
||||
if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF)
|
||||
{
|
||||
sEluna->eventMgr->globalProcessor->AddEvent(functionRef, delay, repeats);
|
||||
Eluna::Push(L, functionRef);
|
||||
else
|
||||
Eluna::Push(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a global timed event specified by the event ID
|
||||
*
|
||||
* @param int eventId : event Id to remove
|
||||
* @param bool all_Events = false : remove from all events, not just global
|
||||
*/
|
||||
int RemoveEventById(lua_State* L)
|
||||
{
|
||||
int eventId = Eluna::CHECKVAL<int>(L, 1);
|
||||
bool all_Events = Eluna::CHECKVAL<bool>(L, 1, false);
|
||||
|
||||
// not thread safe
|
||||
if (all_Events)
|
||||
sEluna->m_EventMgr->RemoveEvent(eventId);
|
||||
sEluna->eventMgr->RemoveEvent(eventId);
|
||||
else
|
||||
sEluna->m_EventMgr->RemoveEvent(&sEluna->m_EventMgr->GlobalEvents, eventId);
|
||||
sEluna->eventMgr->globalProcessor->RemoveEvent(eventId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all global timed events
|
||||
*
|
||||
* @param bool all_Events = false : remove all events, not just global
|
||||
*/
|
||||
int RemoveEvents(lua_State* L)
|
||||
{
|
||||
bool all_Events = Eluna::CHECKVAL<bool>(L, 1, false);
|
||||
|
||||
// not thread safe
|
||||
if (all_Events)
|
||||
sEluna->m_EventMgr->RemoveEvents();
|
||||
sEluna->eventMgr->RemoveEvents();
|
||||
else
|
||||
sEluna->m_EventMgr->GlobalEvents.KillAllEvents(true);
|
||||
sEluna->eventMgr->globalProcessor->RemoveEvents();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -341,13 +341,14 @@ void Eluna::OnShutdownCancel()
|
||||
|
||||
void Eluna::OnWorldUpdate(uint32 diff)
|
||||
{
|
||||
eventMgr->globalProcessor->Update(diff);
|
||||
|
||||
if (reload)
|
||||
{
|
||||
ReloadEluna();
|
||||
return;
|
||||
}
|
||||
|
||||
m_EventMgr->Update(diff);
|
||||
EVENT_BEGIN(ServerEventBindings, WORLD_EVENT_ON_UPDATE, return);
|
||||
Push(L, diff);
|
||||
EVENT_EXECUTE(0);
|
||||
@@ -1834,6 +1835,7 @@ bool Eluna::OnQuestComplete(Player* pPlayer, GameObject* pGameObject, Quest cons
|
||||
|
||||
void Eluna::UpdateAI(GameObject* pGameObject, uint32 diff)
|
||||
{
|
||||
pGameObject->elunaEvents.Update(diff);
|
||||
ENTRY_BEGIN(GameObjectEventBindings, pGameObject->GetEntry(), GAMEOBJECT_EVENT_ON_AIUPDATE, return);
|
||||
Push(L, pGameObject);
|
||||
Push(L, diff);
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
#include "ElunaTemplate.h"
|
||||
#include "ElunaUtility.h"
|
||||
|
||||
// Some dummy includes containing BOOST_VERSION:
|
||||
// ObjectAccessor.h Config.h Log.h
|
||||
#ifdef BOOST_VERSION
|
||||
#ifdef USING_BOOST
|
||||
#include <boost/filesystem.hpp>
|
||||
#else
|
||||
#include <ace/ACE.h>
|
||||
@@ -89,7 +87,7 @@ void Eluna::ReloadEluna()
|
||||
Eluna::Eluna():
|
||||
L(luaL_newstate()),
|
||||
|
||||
m_EventMgr(new EventMgr(*this)),
|
||||
eventMgr(NULL),
|
||||
|
||||
ServerEventBindings(new EventBind<HookMgr::ServerEvents>("ServerEvents", *this)),
|
||||
PlayerEventBindings(new EventBind<HookMgr::PlayerEvents>("PlayerEvents", *this)),
|
||||
@@ -122,6 +120,10 @@ playerGossipBindings(new EntryBind<HookMgr::GossipEvents>("GossipEvents (player)
|
||||
ASSERT(!Eluna::GEluna);
|
||||
Eluna::GEluna = this;
|
||||
|
||||
// Set event manager. Must be after setting sEluna
|
||||
eventMgr = new EventMgr();
|
||||
eventMgr->globalProcessor = new ElunaEventProcessor(NULL);
|
||||
|
||||
// run scripts
|
||||
RunScripts();
|
||||
|
||||
@@ -132,7 +134,7 @@ Eluna::~Eluna()
|
||||
{
|
||||
OnLuaStateClose();
|
||||
|
||||
delete m_EventMgr;
|
||||
delete eventMgr;
|
||||
|
||||
// Replace this with map remove if making multithread version
|
||||
Eluna::GEluna = NULL;
|
||||
@@ -190,7 +192,7 @@ void Eluna::GetScripts(std::string path, ScriptList& scripts)
|
||||
{
|
||||
ELUNA_LOG_DEBUG("[Eluna]: GetScripts from path `%s`", path.c_str());
|
||||
|
||||
#ifdef BOOST_VERSION
|
||||
#ifdef USING_BOOST
|
||||
boost::filesystem::path someDir(path);
|
||||
boost::filesystem::directory_iterator end_iter;
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
lua_State* L;
|
||||
int userdata_table;
|
||||
|
||||
EventMgr* m_EventMgr;
|
||||
EventMgr* eventMgr;
|
||||
|
||||
EventBind<HookMgr::ServerEvents>* ServerEventBindings;
|
||||
EventBind<HookMgr::PlayerEvents>* PlayerEventBindings;
|
||||
|
||||
@@ -192,6 +192,9 @@ ElunaRegister<WorldObject> WorldObjectMethods[] =
|
||||
{ "SummonGameObject", &LuaWorldObject::SummonGameObject }, // :SummonGameObject(entry, x, y, z, o[, respawnDelay]) - Spawns an object to location. Returns the object or nil
|
||||
{ "SpawnCreature", &LuaWorldObject::SpawnCreature }, // :SpawnCreature(entry, x, y, z, o[, spawnType, despawnDelay]) - Spawns a creature to location that despawns after given time (0 for infinite). Returns the creature or nil
|
||||
{ "SendPacket", &LuaWorldObject::SendPacket }, // :SendPacket(packet) - Sends a specified packet to everyone around
|
||||
{ "RegisterEvent", &LuaWorldObject::RegisterEvent },
|
||||
{ "RemoveEventById", &LuaWorldObject::RemoveEventById },
|
||||
{ "RemoveEvents", &LuaWorldObject::RemoveEvents },
|
||||
|
||||
{ NULL, NULL },
|
||||
};
|
||||
@@ -330,9 +333,6 @@ ElunaRegister<Unit> UnitMethods[] =
|
||||
#endif
|
||||
|
||||
// Other
|
||||
{ "RegisterEvent", &LuaUnit::RegisterEvent }, // :RegisterEvent(function, delay, repeats) - The timer ticks if this unit is visible to someone. The function is called with arguments (eventid, delay, repeats, unit) after the time has passed if the unit exists. Returns EventId
|
||||
{ "RemoveEventById", &LuaUnit::RemoveEventById }, // :RemoveEventById(eventID) - Removes a Registered (timed) event by it's ID.
|
||||
{ "RemoveEvents", &LuaUnit::RemoveEvents }, // :RemoveEvents() - Removes all registered timed events
|
||||
{ "AddAura", &LuaUnit::AddAura }, // :AddAura(spellId, target) - Adds an aura to the specified target
|
||||
{ "RemoveAura", &LuaUnit::RemoveAura }, // :RemoveAura(spellId[, casterGUID]) - Removes an aura from the unit by the spellId, casterGUID(Original caster) is optional
|
||||
{ "RemoveAllAuras", &LuaUnit::RemoveAllAuras }, // :RemoveAllAuras() - Removes all the unit's auras
|
||||
@@ -826,9 +826,6 @@ ElunaRegister<GameObject> GameObjectMethods[] =
|
||||
{ "IsSpawned", &LuaGameObject::IsSpawned },
|
||||
|
||||
// Other
|
||||
{ "RegisterEvent", &LuaGameObject::RegisterEvent },
|
||||
{ "RemoveEventById", &LuaGameObject::RemoveEventById },
|
||||
{ "RemoveEvents", &LuaGameObject::RemoveEvents },
|
||||
{ "RemoveFromWorld", &LuaGameObject::RemoveFromWorld },
|
||||
{ "UseDoorOrButton", &LuaGameObject::UseDoorOrButton },
|
||||
{ "Despawn", &LuaGameObject::Despawn },
|
||||
|
||||
@@ -1517,33 +1517,6 @@ namespace LuaUnit
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RegisterEvent(lua_State* L, Unit* unit)
|
||||
{
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
uint32 delay = Eluna::CHECKVAL<uint32>(L, 3);
|
||||
uint32 repeats = Eluna::CHECKVAL<uint32>(L, 4);
|
||||
|
||||
lua_pushvalue(L, 2);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
functionRef = sEluna->m_EventMgr->AddEvent(&unit->m_Events, functionRef, delay, repeats, unit);
|
||||
if (functionRef)
|
||||
Eluna::Push(L, functionRef);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RemoveEventById(lua_State* L, Unit* unit)
|
||||
{
|
||||
int eventId = Eluna::CHECKVAL<int>(L, 2);
|
||||
sEluna->m_EventMgr->RemoveEvent(&unit->m_Events, eventId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RemoveEvents(lua_State* /*L*/, Unit* unit)
|
||||
{
|
||||
sEluna->m_EventMgr->RemoveEvents(&unit->m_Events);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AddUnitState(lua_State* L, Unit* unit)
|
||||
{
|
||||
uint32 state = Eluna::CHECKVAL<uint32>(L, 2);
|
||||
|
||||
@@ -631,5 +631,56 @@ namespace LuaWorldObject
|
||||
Eluna::Push(L, obj->SummonCreature(entry, x, y, z, o, type, despawnTimer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a timed event to the [WorldObject]
|
||||
* When the passed function is called, the parameters `(eventId, delay, repeats, worldobject)` are passed to it.
|
||||
* Repeats will decrease on each call if the event does not repeat indefinitely
|
||||
*
|
||||
* Note that for [Creature] and [GameObject] the timed event timer ticks only if the creature is in sight of someone
|
||||
* For all [WorldObject]s the timed events are removed when the object is destoryed. This means that for example a [Player]'s events are removed on logout.
|
||||
*
|
||||
* @param function function : function to trigger when the time has passed
|
||||
* @param uint32 delay : set time in milliseconds for the event to trigger
|
||||
* @param uint32 repeats : how many times for the event to repeat, 0 is infinite
|
||||
* @return int eventId : unique ID for the timed event used to cancel it or nil
|
||||
*/
|
||||
int RegisterEvent(lua_State* L, WorldObject* obj)
|
||||
{
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
uint32 delay = Eluna::CHECKVAL<uint32>(L, 3);
|
||||
uint32 repeats = Eluna::CHECKVAL<uint32>(L, 4);
|
||||
|
||||
lua_pushvalue(L, 2);
|
||||
int functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF)
|
||||
{
|
||||
obj->elunaEvents.AddEvent(functionRef, delay, repeats);
|
||||
Eluna::Push(L, functionRef);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the timed event from a [WorldObject] by the specified event ID
|
||||
*
|
||||
* @param int eventId : event Id to remove
|
||||
*/
|
||||
int RemoveEventById(lua_State* L, WorldObject* obj)
|
||||
{
|
||||
int eventId = Eluna::CHECKVAL<int>(L, 2);
|
||||
obj->elunaEvents.RemoveEvent(eventId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all timed events from a [WorldObject]
|
||||
*
|
||||
*/
|
||||
int RemoveEvents(lua_State* /*L*/, WorldObject* obj)
|
||||
{
|
||||
obj->elunaEvents.RemoveEvents();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user