From e7019de059a691b03f1a3b2e27ca46bfc68b6646 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Sun, 15 Feb 2015 02:08:23 +0200 Subject: [PATCH] Eluna fix problem with reloading timed events --- ElunaEventMgr.cpp | 37 +++++++++++++++++++++++-------------- ElunaEventMgr.h | 30 ++++++++++++++++++++++-------- GlobalMethods.h | 8 ++++---- LuaEngine.cpp | 2 +- WorldObjectMethods.h | 4 ++-- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/ElunaEventMgr.cpp b/ElunaEventMgr.cpp index 266b9d9..fe364b7 100644 --- a/ElunaEventMgr.cpp +++ b/ElunaEventMgr.cpp @@ -41,9 +41,11 @@ void ElunaEventProcessor::Update(uint32 diff) { LuaEvent* luaEvent = it->second; eventList.erase(it); - eventMap.erase(luaEvent->funcRef); - if (!luaEvent->abort) + if (luaEvent->state != LUAEVENT_STATE_ERASE) + eventMap.erase(luaEvent->funcRef); + + if (luaEvent->state == LUAEVENT_STATE_RUN) { bool remove = luaEvent->repeats == 1; if (!remove) @@ -61,10 +63,12 @@ void ElunaEventProcessor::Update(uint32 diff) } } -void ElunaEventProcessor::RemoveEvents() +void ElunaEventProcessor::SetStates(LuaEventState state) { for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it) - it->second->abort = true; + it->second->SetState(state); + if (state == LUAEVENT_STATE_ERASE) + eventMap.clear(); } void ElunaEventProcessor::RemoveEvents_internal() @@ -83,10 +87,12 @@ void ElunaEventProcessor::RemoveEvents_internal() eventMap.clear(); } -void ElunaEventProcessor::RemoveEvent(int eventId) +void ElunaEventProcessor::SetState(int eventId, LuaEventState state) { if (eventMap.find(eventId) != eventMap.end()) - eventMap[eventId]->abort = true; + eventMap[eventId]->SetState(state); + if (state == LUAEVENT_STATE_ERASE) + eventMap.erase(eventId); } void ElunaEventProcessor::AddEvent(LuaEvent* luaEvent) @@ -102,8 +108,11 @@ void ElunaEventProcessor::AddEvent(int funcRef, uint32 delay, uint32 repeats) void ElunaEventProcessor::RemoveEvent(LuaEvent* luaEvent) { - // Free lua function ref - luaL_unref((*E)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); + if (luaEvent->state != LUAEVENT_STATE_ERASE && Eluna::IsInitialized()) + { + // Free lua function ref + luaL_unref((*E)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); + } delete luaEvent; } @@ -124,20 +133,20 @@ EventMgr::~EventMgr() globalProcessor = NULL; } -void EventMgr::RemoveEvents() +void EventMgr::SetStates(LuaEventState state) { ReadGuard guard(GetLock()); if (!processors.empty()) for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors - (*it)->RemoveEvents(); - globalProcessor->RemoveEvents(); + (*it)->SetStates(state); + globalProcessor->SetStates(state); } -void EventMgr::RemoveEvent(int eventId) +void EventMgr::SetState(int eventId, LuaEventState state) { ReadGuard guard(GetLock()); if (!processors.empty()) for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors - (*it)->RemoveEvent(eventId); - globalProcessor->RemoveEvent(eventId); + (*it)->SetState(eventId, state); + globalProcessor->SetState(eventId, state); } diff --git a/ElunaEventMgr.h b/ElunaEventMgr.h index 01771f5..ecf879e 100644 --- a/ElunaEventMgr.h +++ b/ElunaEventMgr.h @@ -22,16 +22,30 @@ class EventMgr; class ElunaEventProcessor; class WorldObject; +enum LuaEventState +{ + LUAEVENT_STATE_RUN, // On next call run the function normally + LUAEVENT_STATE_ABORT, // On next call unregisters reffed function and erases the data + LUAEVENT_STATE_ERASE, // On next call just erases the data +}; + struct LuaEvent { LuaEvent(int _funcRef, uint32 _delay, uint32 _repeats) : - delay(_delay), repeats(_repeats), funcRef(_funcRef), abort(false) + delay(_delay), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN) { } + + void SetState(LuaEventState _state) + { + if (state != LUAEVENT_STATE_ERASE) + state = _state; + } + uint32 delay; // Delay between event calls uint32 repeats; // Amount of repeats to make, 0 for infinite int funcRef; // Lua function reference ID, also used as event ID - bool abort; // True if aborted and should not execute anymore + LuaEventState state; // State for next call }; class ElunaEventProcessor @@ -47,9 +61,9 @@ public: void Update(uint32 diff); // removes all timed events on next tick or at tick end - void RemoveEvents(); + void SetStates(LuaEventState state); // set the event to be removed when executing - void RemoveEvent(int eventId); + void SetState(int eventId, LuaEventState state); void AddEvent(int funcRef, uint32 delay, uint32 repeats); EventMap eventMap; @@ -74,13 +88,13 @@ public: EventMgr(Eluna** _E); ~EventMgr(); - // Remove all timed events + // Set the state of all timed events // Execute only in safe env - void RemoveEvents(); + void SetStates(LuaEventState state); - // Removes the eventId from all events + // Sets the eventId's state in all processors // Execute only in safe env - void RemoveEvent(int eventId); + void SetState(int eventId, LuaEventState state); }; #endif diff --git a/GlobalMethods.h b/GlobalMethods.h index 6993669..a958552 100644 --- a/GlobalMethods.h +++ b/GlobalMethods.h @@ -1244,9 +1244,9 @@ namespace LuaGlobalFunctions // not thread safe if (all_Events) - E->eventMgr->RemoveEvent(eventId); + E->eventMgr->SetState(eventId, LUAEVENT_STATE_ABORT); else - E->eventMgr->globalProcessor->RemoveEvent(eventId); + E->eventMgr->globalProcessor->SetState(eventId, LUAEVENT_STATE_ABORT); return 0; } @@ -1261,9 +1261,9 @@ namespace LuaGlobalFunctions // not thread safe if (all_Events) - E->eventMgr->RemoveEvents(); + E->eventMgr->SetStates(LUAEVENT_STATE_ABORT); else - E->eventMgr->globalProcessor->RemoveEvents(); + E->eventMgr->globalProcessor->SetStates(LUAEVENT_STATE_ABORT); return 0; } diff --git a/LuaEngine.cpp b/LuaEngine.cpp index eac6eaa..ad7a75f 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -101,7 +101,7 @@ void Eluna::_ReloadEluna() eWorld->SendServerMessage(SERVER_MSG_STRING, "Reloading Eluna..."); // Remove all timed events - sEluna->eventMgr->RemoveEvents(); + sEluna->eventMgr->SetStates(LUAEVENT_STATE_ERASE); // Close lua sEluna->CloseLua(); diff --git a/WorldObjectMethods.h b/WorldObjectMethods.h index 4786583..ffe3bc1 100644 --- a/WorldObjectMethods.h +++ b/WorldObjectMethods.h @@ -645,7 +645,7 @@ namespace LuaWorldObject int RemoveEventById(Eluna* /*E*/, lua_State* L, WorldObject* obj) { int eventId = Eluna::CHECKVAL(L, 2); - obj->elunaEvents->RemoveEvent(eventId); + obj->elunaEvents->SetState(eventId, LUAEVENT_STATE_ABORT); return 0; } @@ -655,7 +655,7 @@ namespace LuaWorldObject */ int RemoveEvents(Eluna* /*E*/, lua_State* /*L*/, WorldObject* obj) { - obj->elunaEvents->RemoveEvents(); + obj->elunaEvents->SetStates(LUAEVENT_STATE_ABORT); return 0; }