/* * Copyright (C) 2010 - 2014 Eluna Lua Engine * This program is free software licensed under GPL version 3 * Please see the included DOCS/LICENSE.md for more information */ #include "ElunaEventMgr.h" #include "LuaEngine.h" #include "Object.h" extern "C" { #include "lua.h" #include "lauxlib.h" }; LuaEvent::LuaEvent(ElunaEventProcessor* _events, int _funcRef, uint32 _delay, uint32 _calls) : to_Abort(false), events(_events), funcRef(_funcRef), delay(_delay), calls(_calls) { } LuaEvent::~LuaEvent() { luaL_unref(sEluna->L, LUA_REGISTRYINDEX, funcRef); // Free lua function ref } void LuaEvent::Execute() { // 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(sEluna->L, events->obj); Eluna::ExecuteCall(sEluna->L, 4, 0); } 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(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::RemoveEvents() { 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) { 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); }