@@ -18,27 +18,19 @@ extern "C"
1818#include " lauxlib.h"
1919};
2020
21- ElunaEventProcessor::ElunaEventProcessor (Eluna* _E, WorldObject* _obj) : m_time(0 ), obj(_obj), E(_E)
22- {
23- if (obj)
24- E->eventMgr ->processors .insert (this );
25- }
26-
2721ElunaEventProcessor::~ElunaEventProcessor ()
2822{
29- {
30- RemoveEvents_internal ();
31- }
32-
33- if (obj)
34- E->eventMgr ->processors .erase (this );
23+ ClearAllEvents ();
3524}
3625
3726void ElunaEventProcessor::Update (uint32 diff)
3827{
28+ isUpdating = true ;
29+
3930 m_time += diff;
40- for (EventList::iterator it = eventList.begin (); it != eventList.end () && it ->first <= m_time; it = eventList. begin () )
31+ while (! eventList.empty () && eventList.begin () ->first <= m_time)
4132 {
33+ auto it = eventList.begin ();
4234 LuaEvent* luaEvent = it->second ;
4335 eventList.erase (it);
4436
@@ -50,11 +42,11 @@ void ElunaEventProcessor::Update(uint32 diff)
5042 uint32 delay = luaEvent->delay ;
5143 bool remove = luaEvent->repeats == 1 ;
5244 if (!remove)
53- AddEvent (luaEvent); // Reschedule before calling incase RemoveEvents used
45+ AddEvent (luaEvent); // may be deferred if we recurse into Update
5446
5547 // Call the timed event
56- if (!obj || (obj && obj->IsInWorld ()))
57- E->OnTimedEvent (luaEvent->funcRef , delay, luaEvent->repeats ? luaEvent->repeats -- : luaEvent->repeats , obj);
48+ if (!obj || (obj && obj->IsInWorld ()))
49+ mgr-> E ->OnTimedEvent (luaEvent->funcRef , delay, luaEvent->repeats ? luaEvent->repeats -- : luaEvent->repeats , obj);
5850
5951 if (!remove)
6052 continue ;
@@ -63,37 +55,68 @@ void ElunaEventProcessor::Update(uint32 diff)
6355 // Event should be deleted (executed last time or set to be aborted)
6456 RemoveEvent (luaEvent);
6557 }
58+
59+ isUpdating = false ;
60+ ProcessDeferredOps ();
6661}
6762
6863void ElunaEventProcessor::SetStates (LuaEventState state)
6964{
70- for (EventList::iterator it = eventList.begin (); it != eventList.end (); ++it)
71- it->second ->SetState (state);
65+ if (isUpdating)
66+ {
67+ QueueDeferredOp (DeferredOpType::SetStates, nullptr , 0 , state);
68+ return ;
69+ }
70+
71+ for (auto & [time, event] : eventList)
72+ event->SetState (state);
73+
7274 if (state == LUAEVENT_STATE_ERASE)
7375 eventMap.clear ();
7476}
7577
76- void ElunaEventProcessor::RemoveEvents_internal ()
78+ void ElunaEventProcessor::ClearAllEvents ()
7779{
78- for (EventList::iterator it = eventList.begin (); it != eventList.end (); ++it)
79- RemoveEvent (it->second );
80+ if (isUpdating)
81+ {
82+ QueueDeferredOp (DeferredOpType::ClearAll);
83+ return ;
84+ }
85+
86+ for (auto & [time, event] : eventList)
87+ RemoveEvent (event);
8088
89+ deferredOps.clear ();
8190 eventList.clear ();
8291 eventMap.clear ();
8392}
8493
8594void ElunaEventProcessor::SetState (int eventId, LuaEventState state)
8695{
87- if (eventMap.find (eventId) != eventMap.end ())
88- eventMap[eventId]->SetState (state);
96+ if (isUpdating)
97+ {
98+ QueueDeferredOp (DeferredOpType::SetState, nullptr , eventId, state);
99+ return ;
100+ }
101+
102+ auto itr = eventMap.find (eventId);
103+ if (itr != eventMap.end ())
104+ itr->second ->SetState (state);
105+
89106 if (state == LUAEVENT_STATE_ERASE)
90107 eventMap.erase (eventId);
91108}
92109
93110void ElunaEventProcessor::AddEvent (LuaEvent* luaEvent)
94111{
112+ if (isUpdating)
113+ {
114+ QueueDeferredOp (DeferredOpType::AddEvent, luaEvent);
115+ return ;
116+ }
117+
95118 luaEvent->GenerateDelay ();
96- eventList.insert (std::pair<uint64, LuaEvent*>( m_time + luaEvent->delay , luaEvent) );
119+ eventList.emplace ( m_time + luaEvent->delay , luaEvent);
97120 eventMap[luaEvent->funcRef ] = luaEvent;
98121}
99122
@@ -105,47 +128,148 @@ void ElunaEventProcessor::AddEvent(int funcRef, uint32 min, uint32 max, uint32 r
105128void ElunaEventProcessor::RemoveEvent (LuaEvent* luaEvent)
106129{
107130 // Unreference if should and if Eluna was not yet uninitialized and if the lua state still exists
108- if (luaEvent->state != LUAEVENT_STATE_ERASE && E->HasLuaState ())
131+ if (luaEvent->state != LUAEVENT_STATE_ERASE && mgr-> E ->HasLuaState ())
109132 {
110133 // Free lua function ref
111- luaL_unref (E->L , LUA_REGISTRYINDEX, luaEvent->funcRef );
134+ luaL_unref (mgr-> E ->L , LUA_REGISTRYINDEX, luaEvent->funcRef );
112135 }
113136 delete luaEvent;
114137}
115138
139+ void ElunaEventProcessor::QueueDeferredOp (DeferredOpType type, LuaEvent* event, int eventId, LuaEventState state)
140+ {
141+ DeferredOp op;
142+ op.type = type;
143+ op.event = event;
144+ op.eventId = eventId;
145+ op.state = state;
146+ deferredOps.push_back (op);
147+ }
148+
149+ void ElunaEventProcessor::ProcessDeferredOps ()
150+ {
151+ if (deferredOps.empty ())
152+ return ;
153+
154+ std::vector<DeferredOp> ops;
155+ ops.swap (deferredOps);
156+
157+ using Handler = void (*)(ElunaEventProcessor*, DeferredOp&);
158+ static constexpr Handler handlers[] =
159+ {
160+ [](ElunaEventProcessor* self, DeferredOp& op) { self->AddEvent (op.event ); },
161+ [](ElunaEventProcessor* self, DeferredOp& op) { self->SetState (op.eventId , op.state ); },
162+ [](ElunaEventProcessor* self, DeferredOp& op) { self->SetStates (op.state ); },
163+ [](ElunaEventProcessor* self, DeferredOp& /* op*/ ) { self->ClearAllEvents (); }
164+ };
165+
166+ for (DeferredOp& op : ops)
167+ {
168+ handlers[op.type ](this , op);
169+ }
170+ }
171+
172+ ElunaProcessorInfo::~ElunaProcessorInfo ()
173+ {
174+ if (mgr)
175+ mgr->FlagObjectProcessorForDeletion (processorId);
176+ }
177+
116178EventMgr::EventMgr (Eluna* _E) : E(_E)
117179{
118- globalProcessor = std::make_unique<ElunaEventProcessor>(E, nullptr );
180+ auto gp = std::make_unique<ElunaEventProcessor>(this , nullptr );
181+ processors.insert (gp.get ());
182+ globalProcessors.emplace (GLOBAL_EVENTS, std::move (gp));
119183}
120184
121185EventMgr::~EventMgr ()
122186{
123- if (!processors. empty ())
124- for (ProcessorSet::const_iterator it = processors. begin (); it != processors. end (); ++it) // loop processors
125- (*it)-> RemoveEvents_internal ();
126- globalProcessor-> RemoveEvents_internal ();
187+ globalProcessors. clear ();
188+ objectProcessors. clear ();
189+ processors. clear ();
190+ objectProcessorsPendingDelete. clear ();
127191}
128192
129193void EventMgr::UpdateProcessors (uint32 diff)
130194{
131- if (!processors.empty ())
132- for (ProcessorSet::const_iterator it = processors.begin (); it != processors.end (); ++it) // loop processors
133- (*it)->Update (diff);
134- globalProcessor->Update (diff);
195+ // iterate a copy because processors may be destroyed during update (creature removed by a script, etc)
196+ ProcessorSet copy = processors;
197+
198+ for (auto * processor : copy)
199+ {
200+ if (processors.find (processor) != processors.end ())
201+ if (!processor->pendingDeletion )
202+ processor->Update (diff);
203+ }
204+
205+ CleanupObjectProcessors ();
135206}
136207
137- void EventMgr::SetStates (LuaEventState state)
208+ void EventMgr::SetAllEventStates (LuaEventState state)
138209{
139- if (!processors.empty ())
140- for (ProcessorSet::const_iterator it = processors.begin (); it != processors.end (); ++it) // loop processors
141- (*it)->SetStates (state);
142- globalProcessor->SetStates (state);
210+ for (auto * processor : processors)
211+ processor->SetStates (state);
143212}
144213
145- void EventMgr::SetState (int eventId, LuaEventState state)
214+ void EventMgr::SetEventState (int eventId, LuaEventState state)
146215{
147- if (!processors.empty ())
148- for (ProcessorSet::const_iterator it = processors.begin (); it != processors.end (); ++it) // loop processors
149- (*it)->SetState (eventId, state);
150- globalProcessor->SetState (eventId, state);
216+ for (auto * processor : processors)
217+ processor->SetState (eventId, state);
218+ }
219+
220+ ElunaEventProcessor* EventMgr::GetGlobalProcessor (GlobalEventSpace space)
221+ {
222+ auto it = globalProcessors.find (space);
223+ return (it != globalProcessors.end ()) ? it->second .get () : nullptr ;
224+ }
225+
226+ uint64 EventMgr::CreateObjectProcessor (WorldObject* obj)
227+ {
228+ uint64 id = obj->GetGUID ().GetRawValue ();
229+ auto proc = std::make_unique<ElunaEventProcessor>(this , obj);
230+ ElunaEventProcessor* raw = proc.get ();
231+
232+ processors.insert (raw);
233+ objectProcessors.emplace (id, std::move (proc));
234+
235+ return id;
236+ }
237+
238+ ElunaEventProcessor* EventMgr::GetObjectProcessor (uint64 processorId)
239+ {
240+ auto it = objectProcessors.find (processorId);
241+ return (it != objectProcessors.end ()) ? it->second .get () : nullptr ;
242+ }
243+
244+ void EventMgr::FlagObjectProcessorForDeletion (uint64 processorId)
245+ {
246+ auto it = objectProcessors.find (processorId);
247+ if (it == objectProcessors.end ())
248+ return ;
249+
250+ ElunaEventProcessor* p = it->second .get ();
251+ if (!p->pendingDeletion )
252+ {
253+ p->pendingDeletion = true ;
254+ p->obj = nullptr ;
255+ objectProcessorsPendingDelete.insert (processorId);
256+ }
257+ }
258+
259+ void EventMgr::CleanupObjectProcessors ()
260+ {
261+ for (uint64 processorId : objectProcessorsPendingDelete)
262+ {
263+ auto it = objectProcessors.find (processorId);
264+ if (it == objectProcessors.end ())
265+ continue ;
266+
267+ ElunaEventProcessor* p = it->second .get ();
268+ p->SetStates (LUAEVENT_STATE_ERASE);
269+
270+ processors.erase (p);
271+ objectProcessors.erase (it);
272+ }
273+
274+ objectProcessorsPendingDelete.clear ();
151275}
0 commit comments