* changed the way how objects are stored. they are now no longer deleted directly, but moved into a *depleted* state. this prevents crashes with already deleted objects accessed by other threads

This commit is contained in:
false_genesis 2008-03-30 23:02:21 +00:00
parent e0a0b7d82d
commit d7ea5fe553
14 changed files with 78 additions and 31 deletions

View File

@ -1016,7 +1016,10 @@ DefReturnResult DefScriptPackage::SCGui(CmdSet &Set)
// TODO: not sure if this piece of code will work as intended, needs some testing // TODO: not sure if this piece of code will work as intended, needs some testing
if(ins->GetWSession() && ins->GetWSession()->InWorld()) if(ins->GetWSession() && ins->GetWSession()->InWorld())
{
ins->GetGUI()->SetSceneState(SCENESTATE_WORLD); ins->GetGUI()->SetSceneState(SCENESTATE_WORLD);
ins->GetWSession()->objmgr.ReNotifyGUI();
}
else else
ins->GetGUI()->SetSceneState(SCENESTATE_GUISTART); ins->GetGUI()->SetSceneState(SCENESTATE_GUISTART);

View File

@ -46,6 +46,7 @@ void DrawObjMgr::Update(void)
while(_add.size()) while(_add.size())
{ {
std::pair<uint64,DrawObject*> p = _add.next(); std::pair<uint64,DrawObject*> p = _add.next();
DEBUG(logdebug("DrawObjMgr: adding DrawObj 0x%X guid "I64FMT" to main storage",p.second,p.first));
_storage[p.first] = p.second; _storage[p.first] = p.second;
} }
@ -55,10 +56,16 @@ void DrawObjMgr::Update(void)
uint64 guid = _del.next(); uint64 guid = _del.next();
if(_storage.find(guid) != _storage.end()) if(_storage.find(guid) != _storage.end())
{ {
DrawObject *o = _storage[guid]; DrawObject *o = _storage[guid];
DEBUG(logdebug("DrawObjMgr: removing DrawObj 0x%X guid "I64FMT" from main storage",o,guid));
_storage.erase(guid); _storage.erase(guid);
delete o; delete o;
} }
else
{
DEBUG(logdebug("DrawObjMgr: ERROR: removable DrawObject "I64FMT" not exising",guid));
}
} }
// now draw everything // now draw everything

View File

@ -226,7 +226,7 @@ void PseuGUI::NotifyObjectDeletion(uint64 guid)
// called from ObjMgr::Add(Object*) // called from ObjMgr::Add(Object*)
void PseuGUI::NotifyObjectCreation(Object *o) void PseuGUI::NotifyObjectCreation(Object *o)
{ {
DrawObject *d = new DrawObject(_smgr,o); DrawObject *d = new DrawObject(_device,o);
domgr.Add(o->GetGUID(),d); domgr.Add(o->GetGUID(),d);
} }

View File

@ -30,6 +30,16 @@ enum DriverIDs
DIRECTX9 = 5, DIRECTX9 = 5,
}; };
#define MOUSE_SENSIVITY 0.5f
#define ANGLE_STEP (M_PI/180.0f)
#define DEG_TO_RAD(x) ((x)*ANGLE_STEP)
#define RAD_TO_DEG(x) ((x)/ANGLE_STEP)
#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) )
#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) )
#define COORD_SCALE_VALUE_X 0.336f
#define COORD_SCALE_VALUE_Y 0.2f
class PseuGUIRunnable : public ZThread::Runnable class PseuGUIRunnable : public ZThread::Runnable
{ {
public: public:

View File

@ -12,18 +12,6 @@
#include "WorldSession.h" #include "WorldSession.h"
#include "World.h" #include "World.h"
#define MOUSE_SENSIVITY 0.5f
#define ANGLE_STEP (M_PI/180)
#define DEG_TO_RAD(x) ((x)*ANGLE_STEP)
#define RAD_TO_DEG(x) ((x)/ANGLE_STEP)
#define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : (x) )
#define DEG_FIX(x) ( (x)>360 ? ((x)-360) : (x) )
#define COORD_SCALE_VALUE_X 0.336f
#define COORD_SCALE_VALUE_Y 0.2f
SceneWorld::SceneWorld(PseuGUI *g) : Scene(g) SceneWorld::SceneWorld(PseuGUI *g) : Scene(g)
{ {
DEBUG(logdebug("SceneWorld: Initializing...")); DEBUG(logdebug("SceneWorld: Initializing..."));
@ -360,8 +348,8 @@ void SceneWorld::SetWorldPosition(WorldPosition wp)
cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE); cam.Z = tile->GetBaseX() - wp.y + (tsize.Height * UNITSIZE);
float heading = RAD_TO_DEG(((M_PI*3.0f)/2.0f) - wp.o); float heading = RAD_TO_DEG(((M_PI*3.0f)/2.0f) - wp.o);
float heading_diff = camera->getHeading() - heading; float heading_diff = camera->getHeading() - heading;
logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading); //logdebug("Setting camera to x: %3f y: %3f z:%3f head: %3f", cam.X, cam.Y, cam.Z, heading);
camera->turnLeft(heading_diff); //camera->turnLeft(heading_diff);
// TODO: // TODO:
// - correct the above formulas // - correct the above formulas

View File

@ -1,6 +1,6 @@
#include "DynamicObject.h" #include "DynamicObject.h"
DynamicObject::DynamicObject() DynamicObject::DynamicObject() : WorldObject()
{ {
_uint32values=NULL; _uint32values=NULL;
_type=TYPE_DYNAMICOBJECT; _type=TYPE_DYNAMICOBJECT;

View File

@ -1,6 +1,6 @@
#include "GameObject.h" #include "GameObject.h"
GameObject::GameObject() GameObject::GameObject() : WorldObject()
{ {
_uint32values=NULL; _uint32values=NULL;
_type=TYPE_GAMEOBJECT; _type=TYPE_GAMEOBJECT;

View File

@ -114,6 +114,7 @@ void WorldSession::_HandleItemQuerySingleResponseOpcode(WorldPacket& recvPacket)
Item::Item() Item::Item()
{ {
_depleted = false;
_type |= TYPE_ITEM; _type |= TYPE_ITEM;
_typeid = TYPEID_ITEM; _typeid = TYPEID_ITEM;

View File

@ -32,24 +32,29 @@ void ObjMgr::RemoveAll(void)
} }
while(_obj.size()) while(_obj.size())
{ {
Remove(_obj.begin()->first); Remove(_obj.begin()->first, true);
} }
} }
void ObjMgr::Remove(uint64 guid) void ObjMgr::Remove(uint64 guid, bool del)
{ {
Object *o = GetObj(guid); Object *o = GetObj(guid, true); // here get also depleted objs and delete if necessary
if(o) if(o)
{ {
o->_SetDepleted();
PseuGUI *gui = _instance->GetGUI(); PseuGUI *gui = _instance->GetGUI();
if(gui) if(gui)
gui->NotifyObjectDeletion(guid); // we have a gui, which must delete linked DrawObject gui->NotifyObjectDeletion(guid); // we have a gui, which must delete linked DrawObject
_obj.erase(guid); // now delete the obj from the mgr if(del)
delete o; // and delete the obj itself {
_obj.erase(guid); // now delete the obj from the mgr
delete o; // and delete the obj itself
}
} }
else else
{ {
_obj.erase(guid); _obj.erase(guid); // we can safely erase an object that does not exist
// - if we reach this point there was a bug anyway
logcustom(2,LRED,"ObjMgr::Remove("I64FMT") - not existing",guid); logcustom(2,LRED,"ObjMgr::Remove("I64FMT") - not existing",guid);
} }
} }
@ -58,20 +63,29 @@ void ObjMgr::Remove(uint64 guid)
void ObjMgr::Add(Object *o) void ObjMgr::Add(Object *o)
{ {
_obj[o->GetGUID()] = o; Object *ox = GetObj(o->GetGUID(),true); // if an object already exists in the mgr, store old ptr...
_obj[o->GetGUID()] = o; // ...assign new one...
if(ox) // and if != NULL, delete the old object (completely, from memory)
{
Remove(ox->GetGUID(),true);
}
PseuGUI *gui = _instance->GetGUI(); PseuGUI *gui = _instance->GetGUI();
if(gui) if(gui)
gui->NotifyObjectCreation(o); gui->NotifyObjectCreation(o);
} }
Object *ObjMgr::GetObj(uint64 guid) Object *ObjMgr::GetObj(uint64 guid, bool also_depleted)
{ {
if(!guid) if(!guid)
return NULL; return NULL;
for(ObjectMap::iterator i = _obj.begin(); i!=_obj.end(); i++) for(ObjectMap::iterator i = _obj.begin(); i!=_obj.end(); i++)
if(i->second->GetGUID() == guid) if(i->second->GetGUID() == guid)
{
if(i->second->_IsDepleted() && !also_depleted)
return NULL;
return i->second; return i->second;
}
return NULL; return NULL;
} }
@ -90,6 +104,22 @@ uint32 ObjMgr::AssignNameToObj(uint32 entry, uint8 type, std::string name)
return changed; return changed;
} }
void ObjMgr::ReNotifyGUI(void)
{
PseuGUI *gui = _instance->GetGUI();
if(!gui)
return;
for(ObjectMap::iterator it = _obj.begin(); it != _obj.end(); it++)
{
Object *o = it->second;
if(o->_IsDepleted())
continue;
gui->NotifyObjectCreation(o);
}
}
// -- Item part -- // -- Item part --
void ObjMgr::Add(ItemProto *proto) void ObjMgr::Add(ItemProto *proto)

View File

@ -49,10 +49,11 @@ public:
// Object functions // Object functions
void Add(Object*); void Add(Object*);
void Remove(uint64); // remove all objects with that guid (should be only 1 object in total anyway) void Remove(uint64 guid, bool del); // remove all objects with that guid (should be only 1 object in total anyway)
Object *GetObj(uint64 guid); Object *GetObj(uint64 guid, bool also_depleted = false);
inline uint32 GetObjectCount(void) { return _obj.size(); } inline uint32 GetObjectCount(void) { return _obj.size(); }
uint32 AssignNameToObj(uint32 entry, uint8 type, std::string name); uint32 AssignNameToObj(uint32 entry, uint8 type, std::string name);
void ReNotifyGUI(void);
private: private:
ItemProtoMap _iproto; ItemProtoMap _iproto;

View File

@ -5,6 +5,7 @@
Object::Object() Object::Object()
{ {
_depleted = false;
_uint32values=NULL; _uint32values=NULL;
_type=TYPE_OBJECT; _type=TYPE_OBJECT;
_typeid=TYPEID_OBJECT; _typeid=TYPEID_OBJECT;
@ -39,6 +40,7 @@ void Object::Create( uint64 guid )
WorldObject::WorldObject() WorldObject::WorldObject()
{ {
_depleted = false;
_m = 0; _m = 0;
} }
@ -121,7 +123,7 @@ void WorldSession::_HandleDestroyObjectOpcode(WorldPacket& recvPacket)
GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set); GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set);
} }
objmgr.Remove(guid); objmgr.Remove(guid, false);
} }

View File

@ -92,6 +92,8 @@ public:
} }
void Create(uint64 guid); void Create(uint64 guid);
inline bool _IsDepleted(void) { return _depleted; }
inline void _SetDepleted(void) { _depleted = true; }
protected: protected:
Object(); Object();
@ -106,6 +108,7 @@ protected:
uint8 _type; uint8 _type;
uint8 _typeid; uint8 _typeid;
std::string _name; std::string _name;
bool _depleted : 1; // true if the object was deleted from the objmgr, but not from memory
}; };
class WorldObject : public Object class WorldObject : public Object

View File

@ -86,7 +86,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
if(uguid != GetGuid()) if(uguid != GetGuid())
{ {
logdev("- already exists, deleting old, creating new object"); logdev("- already exists, deleting old, creating new object");
objmgr.Remove(uguid); objmgr.Remove(uguid, false);
// do not call script here, since the object does not really get deleted // do not call script here, since the object does not really get deleted
} }
else else
@ -128,6 +128,8 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
} }
case TYPEID_PLAYER: case TYPEID_PLAYER:
{ {
if(GetGuid() == uguid) // objmgr.Add() would cause quite some trouble if we added ourself again
break;
Player *player = new Player(); Player *player = new Player();
player->Create(uguid); player->Create(uguid);
objmgr.Add(player); objmgr.Add(player);
@ -201,7 +203,7 @@ void WorldSession::_HandleUpdateObjectOpcode(WorldPacket& recvPacket)
GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set); GetInstance()->GetScripts()->RunScript("_onobjectdelete", &Set);
} }
objmgr.Remove(uguid); objmgr.Remove(uguid, false);
} }
} }
break; break;

View File

@ -597,8 +597,8 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
// that means even if the server sends create object with that guid, do NOT recreate it!! // that means even if the server sends create object with that guid, do NOT recreate it!!
MyCharacter *my = new MyCharacter(); MyCharacter *my = new MyCharacter();
my->Create(_myGUID); my->Create(_myGUID);
objmgr.Add(my);
my->SetName(plr[charId]._name); my->SetName(plr[charId]._name);
objmgr.Add(my);
// TODO: initialize the world here, and load required maps. // TODO: initialize the world here, and load required maps.
// must remove appropriate code from _HandleLoginVerifyWorldOpcode() then!! // must remove appropriate code from _HandleLoginVerifyWorldOpcode() then!!