* fixed problems with too early deleted DrawObjects and one crash with GetSceneState() accessing just deleted _scene. both related to reconnect after connection closed.

This commit is contained in:
false_genesis 2008-04-09 18:11:01 +00:00
parent e06eb019d0
commit 5d418facbe
6 changed files with 34 additions and 9 deletions

View File

@ -27,6 +27,10 @@ void DrawObjMgr::Clear(void)
{ {
delete _add.next().second; delete _add.next().second;
} }
while(_del.size())
{
_del.next();
}
} }
void DrawObjMgr::Add(uint64 objguid, DrawObject *o) void DrawObjMgr::Add(uint64 objguid, DrawObject *o)

View File

@ -246,6 +246,11 @@ void PseuGUI::NotifyObjectCreation(Object *o)
domgr.Add(o->GetGUID(),d); domgr.Add(o->GetGUID(),d);
} }
void PseuGUI::NotifyAllObjectsDeletion(void)
{
domgr.Clear();
}
void PseuGUI::SetInstance(PseuInstance* in) void PseuGUI::SetInstance(PseuInstance* in)
{ {
_instance = in; _instance = in;
@ -264,22 +269,26 @@ void PseuGUI::_UpdateSceneState(void)
{ {
_scene->OnDelete(); _scene->OnDelete();
delete _scene; delete _scene;
_scene = NULL;
} }
_smgr->clear(); _smgr->clear();
_guienv->clear(); _guienv->clear();
_scenestate = _scenestate_new;
logdebug("PseuGUI: switched to SceneState %u", _scenestate);
switch (_scenestate) logdebug("PseuGUI: switching to SceneState %u", _scenestate_new);
switch (_scenestate_new)
{ {
case SCENESTATE_GUISTART: _scene = new SceneGuiStart(this); break; case SCENESTATE_GUISTART: _scene = new SceneGuiStart(this); break;
case SCENESTATE_LOGINSCREEN: _scene = new SceneLogin(this); break; case SCENESTATE_LOGINSCREEN: _scene = new SceneLogin(this); break;
case SCENESTATE_WORLD: _scene = new SceneWorld(this); break; case SCENESTATE_WORLD: _scene = new SceneWorld(this); break;
default: _scene = new Scene(this); // will draw nothing, just yield the gui default: _scene = new Scene(this); // will draw nothing, just yield the gui
} }
_scene->SetState(_scenestate); _scene->SetState(_scenestate_new);
// current scenestate can be set safely after scene is created and ready
_scenestate = _scenestate_new;
logdebug("PseuGUI: scene created."); logdebug("PseuGUI: scene created.");
} }
@ -295,9 +304,11 @@ bool PseuGUI::SetSceneData(uint32 index, uint32 value)
uint32 PseuGUI::GetSceneState(void) uint32 PseuGUI::GetSceneState(void)
{ {
/* // not good, not threadsafe! (can crash)
if(!_scene) if(!_scene)
return SCENESTATE_NOSCENE; return SCENESTATE_NOSCENE;
return _scene->GetState(); return _scene->GetState();*/
return _scenestate;
} }

View File

@ -15,7 +15,8 @@ enum SceneState
SCENESTATE_NULL = 0, SCENESTATE_NULL = 0,
SCENESTATE_GUISTART, SCENESTATE_GUISTART,
SCENESTATE_LOGINSCREEN, SCENESTATE_LOGINSCREEN,
SCENESTATE_CHARACTERSELECTION, SCENESTATE_REALMSELECT,
SCENESTATE_CHARSELECT,
SCENESTATE_LOADING, SCENESTATE_LOADING,
SCENESTATE_WORLD, SCENESTATE_WORLD,
SCENESTATE_NOSCENE = 0xFFFFFFFF SCENESTATE_NOSCENE = 0xFFFFFFFF
@ -93,6 +94,7 @@ public:
// interfaces to tell the gui what to draw // interfaces to tell the gui what to draw
void NotifyObjectDeletion(uint64 guid); void NotifyObjectDeletion(uint64 guid);
void NotifyObjectCreation(Object *o); void NotifyObjectCreation(Object *o);
void NotifyAllObjectsDeletion(void);
// scenes // scenes
void SetSceneState(SceneState); void SetSceneState(SceneState);

View File

@ -261,6 +261,7 @@ void SceneWorld::OnDraw(void)
void SceneWorld::OnDelete(void) void SceneWorld::OnDelete(void)
{ {
DEBUG(logdebug("~SceneWorld()")); DEBUG(logdebug("~SceneWorld()"));
gui->domgr.Clear();
//sky->drop(); //sky->drop();
} }

View File

@ -34,6 +34,12 @@ void ObjMgr::RemoveAll(void)
{ {
Remove(_obj.begin()->first, true); Remove(_obj.begin()->first, true);
} }
if(PseuGUI *gui = _instance->GetGUI())
{
// necessary that the pending-to-delete GUIDs just stored by deleting the objects above will be cleared
// so that newly added DrawObjects with uncleared pending-to-delete GUIDs will not get deleted again immediately.
gui->NotifyAllObjectsDeletion();
}
} }
void ObjMgr::Remove(uint64 guid, bool del) void ObjMgr::Remove(uint64 guid, bool del)
@ -42,6 +48,8 @@ void ObjMgr::Remove(uint64 guid, bool del)
if(o) if(o)
{ {
o->_SetDepleted(); o->_SetDepleted();
if(!del)
logdebug("ObjMgr: "I64FMT" '%s' -> depleted.",guid,o->GetName().c_str());
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

View File

@ -42,10 +42,9 @@ WorldSession::~WorldSession()
{ {
if(PseuGUI *gui = GetInstance()->GetGUI()) if(PseuGUI *gui = GetInstance()->GetGUI())
{ {
if(gui->GetSceneState() == SCENESTATE_WORLD)
gui->SetSceneState(SCENESTATE_LOGINSCREEN); // kick back to login gui gui->SetSceneState(SCENESTATE_LOGINSCREEN); // kick back to login gui
logdebug("~WorldSession(): Waiting until world GUI is deleted"); logdebug("~WorldSession(): Waiting until world GUI is deleted");
while(gui->GetSceneState() == SCENESTATE_GUISTART) // .. and wait until the world gui is really deleted while(gui->GetSceneState() != SCENESTATE_LOGINSCREEN) // .. and wait until the world gui is really deleted
GetInstance()->Sleep(1); // (it can cause crash otherwise) GetInstance()->Sleep(1); // (it can cause crash otherwise)
logdebug("~WorldSession(): ... world GUI deleted, continuing to close session"); logdebug("~WorldSession(): ... world GUI deleted, continuing to close session");
} }