* hopefully fixed possible crash when a script called by an event added or deleted events

* improved TypeStorage a bit (speedup?)
This commit is contained in:
false_genesis 2008-02-14 17:19:49 +00:00
parent b73017bccb
commit 281962dad0
5 changed files with 79 additions and 52 deletions

View File

@ -5,83 +5,99 @@ struct DefScript_DynamicEvent
{ {
std::string name, cmd, parent; std::string name, cmd, parent;
clock_t counter, interval; clock_t counter, interval;
bool ran; // if a script has an execution time longer then the interval, and modifies an event, need to check if the event was already triggered, to prevent endless loop
}; };
DefScript_DynamicEventMgr::DefScript_DynamicEventMgr(DefScriptPackage *pack) DefScript_DynamicEventMgr::DefScript_DynamicEventMgr(DefScriptPackage *pack)
{ {
_pack = pack; _pack = pack;
_lastclock = clock(); _lastclock = clock();
_events_changed = false;
} }
DefScript_DynamicEventMgr::~DefScript_DynamicEventMgr() DefScript_DynamicEventMgr::~DefScript_DynamicEventMgr()
{ {
for(DefDynamicEventList::iterator i = _storage.begin(); i != _storage.end(); i++) _storage.Clear();
{
delete *i;
}
} }
void DefScript_DynamicEventMgr::Add(std::string name, std::string script, clock_t interval, const char *parent) void DefScript_DynamicEventMgr::Add(std::string name, std::string script, clock_t interval, const char *parent, bool force)
{ {
_DEFSC_DEBUG( printf("DEFSCRIPT: Add Event %s, interval=%u, parent=%s\n",name.c_str(),interval,parent?parent:""); printf("DEFSCRIPT: EventRun='%s'\n",script.c_str()); ) _DEFSC_DEBUG( printf("DEFSCRIPT: Add Event %s, interval=%u, parent=%s\n",name.c_str(),interval,parent?parent:""); printf("DEFSCRIPT: EventRun='%s'\n",script.c_str()); )
if(name.empty() || script.empty() || interval==0) if(name.empty() || script.empty() || interval==0)
return; return;
for(DefDynamicEventList::iterator i = _storage.begin(); i != _storage.end(); i++) if(_storage.Exists(name) && !force)
if((*i)->name == name) return;
return; // event with that name is already registered
DefScript_DynamicEvent *e = new DefScript_DynamicEvent; DefScript_DynamicEvent *e = _storage.Get(name);
e->name = name; e->name = name;
e->cmd = script; e->cmd = script;
e->interval = interval; e->interval = interval;
e->parent = parent?parent:""; e->parent = parent?parent:"";
e->counter = 0; e->counter = 0;
_storage.push_back(e); e->ran = false;
_events_changed = true;
} }
void DefScript_DynamicEventMgr::Remove(std::string name) void DefScript_DynamicEventMgr::Remove(std::string name)
{ {
if(name.empty()) _storage.Delete(name);
return; _events_changed = true;
for(DefDynamicEventList::iterator i = _storage.begin(); i != _storage.end(); i++)
{
if((*i)->name == name)
{
delete *i;
_storage.erase(i);
break;
}
}
return;
} }
void DefScript_DynamicEventMgr::Update(void) void DefScript_DynamicEventMgr::Update(void)
{ {
bool decr_timer = false;
clock_t diff = clock() - _lastclock; clock_t diff = clock() - _lastclock;
_lastclock = clock(); _lastclock = clock();
DefScript *sc; DefScript *sc;
for(DefDynamicEventList::iterator i = _storage.begin(); i != _storage.end(); i++) DefScript_DynamicEvent *e;
_events_changed = false;
for(std::map<std::string,DefScript_DynamicEvent*>::iterator i = _storage.GetMap().begin(); i != _storage.GetMap().end(); i++ )
{ {
i->second->ran = false;
}
for(std::map<std::string,DefScript_DynamicEvent*>::iterator i = _storage.GetMap().begin(); i != _storage.GetMap().end(); )
{
e = i->second;
sc = NULL; sc = NULL;
try try
{ {
(*i)->counter += diff; e->counter += diff;
if((*i)->counter >= (*i)->interval) if(e->counter >= e->interval && !e->ran)
{ {
(*i)->counter %= (*i)->interval; decr_timer = true;
if(!(*i)->parent.empty()) if(!e->parent.empty())
sc = _pack->GetScript((*i)->parent); sc = _pack->GetScript(e->parent);
if(sc) if(sc)
_pack->RunSingleLineFromScript((*i)->cmd,sc); _pack->RunSingleLineFromScript(e->cmd,sc);
else else
_pack->RunSingleLine((*i)->cmd); _pack->RunSingleLine(e->cmd);
} }
} }
catch (...) catch (...)
{ {
printf("Error in DefScript_DynamicEventMgr::Update()\n"); printf("Error in DefScript_DynamicEventMgr::Update()\n");
return;
} }
if(decr_timer)
{
e->counter %= e->interval;
e->ran = true;
decr_timer = false;
}
if(_events_changed)
{
_events_changed = false;
i = _storage.GetMap().begin();
}
else
{
i++;
}
} }
} }

View File

@ -5,24 +5,27 @@
#include <list> #include <list>
#include <string> #include <string>
#include "TypeStorage.h"
struct DefScript_DynamicEvent; struct DefScript_DynamicEvent;
class DefScript; class DefScript;
class DefScriptPackage; class DefScriptPackage;
typedef std::list<DefScript_DynamicEvent*> DefDynamicEventList; typedef TypeStorage<DefScript_DynamicEvent> DefDynamicEventStorage;
class DefScript_DynamicEventMgr class DefScript_DynamicEventMgr
{ {
public: public:
DefScript_DynamicEventMgr(DefScriptPackage *pack); DefScript_DynamicEventMgr(DefScriptPackage *pack);
~DefScript_DynamicEventMgr(); ~DefScript_DynamicEventMgr();
void Add(std::string name, std::string script, clock_t interval, const char *parent); void Add(std::string name, std::string script, clock_t interval, const char *parent, bool force = false);
void Remove(std::string name); void Remove(std::string name);
void Update(void); void Update(void);
private: private:
DefDynamicEventList _storage; DefDynamicEventStorage _storage;
clock_t _lastclock; clock_t _lastclock;
DefScriptPackage *_pack; DefScriptPackage *_pack;
bool _events_changed; // this one helps to detect if a script called from an event has modified the event storage (risk of iterator invalidation!)
}; };
#endif #endif

View File

@ -7,6 +7,7 @@
template <class T> class TypeStorage template <class T> class TypeStorage
{ {
public: public:
TypeStorage() { _keep = false; }
~TypeStorage(); ~TypeStorage();
bool Exists(std::string); bool Exists(std::string);
void Delete(std::string); void Delete(std::string);
@ -17,27 +18,27 @@ public:
void Unlink(std::string); void Unlink(std::string);
void UnlinkByPtr(T*); void UnlinkByPtr(T*);
std::string GetNameByPtr(T*); std::string GetNameByPtr(T*);
inline std::map<std::string,T*> &GetMap(void) { return _storage; }
inline bool SetKeepOnDestruct(bool b = true) { _keep = true; }
inline unsigned int Size(void) { return _storage.size(); }
void Clear(bool keep = false);
private: private:
T *_Create(std::string); T *_Create(std::string);
std::map<std::string,T*> _storage; std::map<std::string,T*> _storage;
bool _keep;
}; };
// check whether an object with this name is already present // check whether an object with this name is already present
template<class T> bool TypeStorage<T>::Exists(std::string s) template<class T> bool TypeStorage<T>::Exists(std::string s)
{ {
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++) return _storage.find(s) != _storage.end();
{
if(it->first == s)
return true;
}
return false;
} }
// helper to create and assign a new object // helper to create and assign a new object
template<class T> T *TypeStorage<T>::_Create(std::string s) template<class T> T *TypeStorage<T>::_Create(std::string s)
{ {
T *elem = new T(); T *elem = new T;
_storage[s] = elem; _storage[s] = elem;
return elem; return elem;
} }
@ -45,14 +46,11 @@ template<class T> T *TypeStorage<T>::_Create(std::string s)
// delete object with that name, if present // delete object with that name, if present
template<class T> void TypeStorage<T>::Delete(std::string s) template<class T> void TypeStorage<T>::Delete(std::string s)
{ {
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++) std::map<std::string,T*>::iterator it = _storage.find(s);
if(it != _storage.end())
{ {
if(it->first == s) delete it->second;
{ _storage.erase(it);
delete it->second;
_storage.erase(it);
return;
}
} }
} }
@ -73,9 +71,9 @@ template<class T> void TypeStorage<T>::DeleteByPtr(T *ptr)
// return the the object with that name. return NULL if not found // return the the object with that name. return NULL if not found
template <class T> T *TypeStorage<T>::GetNoCreate(std::string s) template <class T> T *TypeStorage<T>::GetNoCreate(std::string s)
{ {
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++) std::map<std::string,T*>::iterator it = _storage.find(s);
if(it->first == s) if(it != _storage.end())
return it->second; return it->second;
return NULL; return NULL;
} }
@ -89,6 +87,16 @@ template<class T> T *TypeStorage<T>::Get(std::string s)
// when destroying the TypeStorage, delete all stored objects // when destroying the TypeStorage, delete all stored objects
template<class T> TypeStorage<T>::~TypeStorage() template<class T> TypeStorage<T>::~TypeStorage()
{ {
Clear(_keep);
}
template<class T> void TypeStorage<T>::Clear(bool keep)
{
if(keep)
{
_storage.clear();
return;
}
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end();) for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end();)
{ {
delete it->second; delete it->second;

View File

@ -18,7 +18,7 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
recvPacket >> proto->SubClass; recvPacket >> proto->SubClass;
recvPacket >> unk; // dont need that value? recvPacket >> unk; // dont need that value?
recvPacket >> proto->Name; recvPacket >> proto->Name;
recvPacket >> s >> s >> s; // strip name1-4 recvPacket >> s >> s >> s; // strip name2-4
recvPacket >> proto->DisplayInfoID; recvPacket >> proto->DisplayInfoID;
recvPacket >> proto->Quality; recvPacket >> proto->Quality;
recvPacket >> proto->Flags; recvPacket >> proto->Flags;

View File

@ -70,7 +70,7 @@ Object *ObjMgr::GetObj(uint64 guid)
return NULL; return NULL;
} }
// iterate over all objects and assign a name to all matching the entry and typemask // iterate over all objects and assign a name to all matching the entry and typeid
uint32 ObjMgr::AssignNameToObj(uint32 entry, uint8 type, std::string name) uint32 ObjMgr::AssignNameToObj(uint32 entry, uint8 type, std::string name)
{ {
uint32 changed = 0; uint32 changed = 0;