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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user