Eluna fix problem with reloading timed events

This commit is contained in:
Rochet2
2015-02-15 02:08:23 +02:00
parent 6a731d24ea
commit e7019de059
5 changed files with 52 additions and 29 deletions

View File

@@ -41,9 +41,11 @@ void ElunaEventProcessor::Update(uint32 diff)
{ {
LuaEvent* luaEvent = it->second; LuaEvent* luaEvent = it->second;
eventList.erase(it); 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; bool remove = luaEvent->repeats == 1;
if (!remove) 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) 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() void ElunaEventProcessor::RemoveEvents_internal()
@@ -83,10 +87,12 @@ void ElunaEventProcessor::RemoveEvents_internal()
eventMap.clear(); eventMap.clear();
} }
void ElunaEventProcessor::RemoveEvent(int eventId) void ElunaEventProcessor::SetState(int eventId, LuaEventState state)
{ {
if (eventMap.find(eventId) != eventMap.end()) 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) void ElunaEventProcessor::AddEvent(LuaEvent* luaEvent)
@@ -102,8 +108,11 @@ void ElunaEventProcessor::AddEvent(int funcRef, uint32 delay, uint32 repeats)
void ElunaEventProcessor::RemoveEvent(LuaEvent* luaEvent) void ElunaEventProcessor::RemoveEvent(LuaEvent* luaEvent)
{ {
// Free lua function ref if (luaEvent->state != LUAEVENT_STATE_ERASE && Eluna::IsInitialized())
luaL_unref((*E)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); {
// Free lua function ref
luaL_unref((*E)->L, LUA_REGISTRYINDEX, luaEvent->funcRef);
}
delete luaEvent; delete luaEvent;
} }
@@ -124,20 +133,20 @@ EventMgr::~EventMgr()
globalProcessor = NULL; globalProcessor = NULL;
} }
void EventMgr::RemoveEvents() void EventMgr::SetStates(LuaEventState state)
{ {
ReadGuard guard(GetLock()); ReadGuard guard(GetLock());
if (!processors.empty()) if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvents(); (*it)->SetStates(state);
globalProcessor->RemoveEvents(); globalProcessor->SetStates(state);
} }
void EventMgr::RemoveEvent(int eventId) void EventMgr::SetState(int eventId, LuaEventState state)
{ {
ReadGuard guard(GetLock()); ReadGuard guard(GetLock());
if (!processors.empty()) if (!processors.empty())
for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors for (ProcessorSet::const_iterator it = processors.begin(); it != processors.end(); ++it) // loop processors
(*it)->RemoveEvent(eventId); (*it)->SetState(eventId, state);
globalProcessor->RemoveEvent(eventId); globalProcessor->SetState(eventId, state);
} }

View File

@@ -22,16 +22,30 @@ class EventMgr;
class ElunaEventProcessor; class ElunaEventProcessor;
class WorldObject; 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 struct LuaEvent
{ {
LuaEvent(int _funcRef, uint32 _delay, uint32 _repeats) : 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 delay; // Delay between event calls
uint32 repeats; // Amount of repeats to make, 0 for infinite uint32 repeats; // Amount of repeats to make, 0 for infinite
int funcRef; // Lua function reference ID, also used as event ID 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 class ElunaEventProcessor
@@ -47,9 +61,9 @@ public:
void Update(uint32 diff); void Update(uint32 diff);
// removes all timed events on next tick or at tick end // 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 // 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); void AddEvent(int funcRef, uint32 delay, uint32 repeats);
EventMap eventMap; EventMap eventMap;
@@ -74,13 +88,13 @@ public:
EventMgr(Eluna** _E); EventMgr(Eluna** _E);
~EventMgr(); ~EventMgr();
// Remove all timed events // Set the state of all timed events
// Execute only in safe env // 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 // Execute only in safe env
void RemoveEvent(int eventId); void SetState(int eventId, LuaEventState state);
}; };
#endif #endif

View File

@@ -1244,9 +1244,9 @@ namespace LuaGlobalFunctions
// not thread safe // not thread safe
if (all_Events) if (all_Events)
E->eventMgr->RemoveEvent(eventId); E->eventMgr->SetState(eventId, LUAEVENT_STATE_ABORT);
else else
E->eventMgr->globalProcessor->RemoveEvent(eventId); E->eventMgr->globalProcessor->SetState(eventId, LUAEVENT_STATE_ABORT);
return 0; return 0;
} }
@@ -1261,9 +1261,9 @@ namespace LuaGlobalFunctions
// not thread safe // not thread safe
if (all_Events) if (all_Events)
E->eventMgr->RemoveEvents(); E->eventMgr->SetStates(LUAEVENT_STATE_ABORT);
else else
E->eventMgr->globalProcessor->RemoveEvents(); E->eventMgr->globalProcessor->SetStates(LUAEVENT_STATE_ABORT);
return 0; return 0;
} }

View File

@@ -101,7 +101,7 @@ void Eluna::_ReloadEluna()
eWorld->SendServerMessage(SERVER_MSG_STRING, "Reloading Eluna..."); eWorld->SendServerMessage(SERVER_MSG_STRING, "Reloading Eluna...");
// Remove all timed events // Remove all timed events
sEluna->eventMgr->RemoveEvents(); sEluna->eventMgr->SetStates(LUAEVENT_STATE_ERASE);
// Close lua // Close lua
sEluna->CloseLua(); sEluna->CloseLua();

View File

@@ -645,7 +645,7 @@ namespace LuaWorldObject
int RemoveEventById(Eluna* /*E*/, lua_State* L, WorldObject* obj) int RemoveEventById(Eluna* /*E*/, lua_State* L, WorldObject* obj)
{ {
int eventId = Eluna::CHECKVAL<int>(L, 2); int eventId = Eluna::CHECKVAL<int>(L, 2);
obj->elunaEvents->RemoveEvent(eventId); obj->elunaEvents->SetState(eventId, LUAEVENT_STATE_ABORT);
return 0; return 0;
} }
@@ -655,7 +655,7 @@ namespace LuaWorldObject
*/ */
int RemoveEvents(Eluna* /*E*/, lua_State* /*L*/, WorldObject* obj) int RemoveEvents(Eluna* /*E*/, lua_State* /*L*/, WorldObject* obj)
{ {
obj->elunaEvents->RemoveEvents(); obj->elunaEvents->SetStates(LUAEVENT_STATE_ABORT);
return 0; return 0;
} }