From 5d418facbed60b12a6635e63807e09a9d8b7b239 Mon Sep 17 00:00:00 2001 From: false_genesis Date: Wed, 9 Apr 2008 18:11:01 +0000 Subject: [PATCH] * fixed problems with too early deleted DrawObjects and one crash with GetSceneState() accessing just deleted _scene. both related to reconnect after connection closed. --- src/Client/GUI/DrawObjMgr.cpp | 4 ++++ src/Client/GUI/PseuGUI.cpp | 21 ++++++++++++++++----- src/Client/GUI/PseuGUI.h | 4 +++- src/Client/GUI/SceneWorld.cpp | 1 + src/Client/World/ObjMgr.cpp | 8 ++++++++ src/Client/World/WorldSession.cpp | 5 ++--- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/Client/GUI/DrawObjMgr.cpp b/src/Client/GUI/DrawObjMgr.cpp index cb10cc7..773a0a3 100644 --- a/src/Client/GUI/DrawObjMgr.cpp +++ b/src/Client/GUI/DrawObjMgr.cpp @@ -27,6 +27,10 @@ void DrawObjMgr::Clear(void) { delete _add.next().second; } + while(_del.size()) + { + _del.next(); + } } void DrawObjMgr::Add(uint64 objguid, DrawObject *o) diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index b5b61c0..cc54700 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -246,6 +246,11 @@ void PseuGUI::NotifyObjectCreation(Object *o) domgr.Add(o->GetGUID(),d); } +void PseuGUI::NotifyAllObjectsDeletion(void) +{ + domgr.Clear(); +} + void PseuGUI::SetInstance(PseuInstance* in) { _instance = in; @@ -264,22 +269,26 @@ void PseuGUI::_UpdateSceneState(void) { _scene->OnDelete(); delete _scene; + _scene = NULL; } _smgr->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_LOGINSCREEN: _scene = new SceneLogin(this); break; case SCENESTATE_WORLD: _scene = new SceneWorld(this); break; 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."); } @@ -295,9 +304,11 @@ bool PseuGUI::SetSceneData(uint32 index, uint32 value) uint32 PseuGUI::GetSceneState(void) { + /* // not good, not threadsafe! (can crash) if(!_scene) return SCENESTATE_NOSCENE; - return _scene->GetState(); + return _scene->GetState();*/ + return _scenestate; } diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index e1cb022..e7f7243 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -15,7 +15,8 @@ enum SceneState SCENESTATE_NULL = 0, SCENESTATE_GUISTART, SCENESTATE_LOGINSCREEN, - SCENESTATE_CHARACTERSELECTION, + SCENESTATE_REALMSELECT, + SCENESTATE_CHARSELECT, SCENESTATE_LOADING, SCENESTATE_WORLD, SCENESTATE_NOSCENE = 0xFFFFFFFF @@ -93,6 +94,7 @@ public: // interfaces to tell the gui what to draw void NotifyObjectDeletion(uint64 guid); void NotifyObjectCreation(Object *o); + void NotifyAllObjectsDeletion(void); // scenes void SetSceneState(SceneState); diff --git a/src/Client/GUI/SceneWorld.cpp b/src/Client/GUI/SceneWorld.cpp index 9c831bc..b80a01e 100644 --- a/src/Client/GUI/SceneWorld.cpp +++ b/src/Client/GUI/SceneWorld.cpp @@ -261,6 +261,7 @@ void SceneWorld::OnDraw(void) void SceneWorld::OnDelete(void) { DEBUG(logdebug("~SceneWorld()")); + gui->domgr.Clear(); //sky->drop(); } diff --git a/src/Client/World/ObjMgr.cpp b/src/Client/World/ObjMgr.cpp index 2fc4f98..2969525 100644 --- a/src/Client/World/ObjMgr.cpp +++ b/src/Client/World/ObjMgr.cpp @@ -34,6 +34,12 @@ void ObjMgr::RemoveAll(void) { 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) @@ -42,6 +48,8 @@ void ObjMgr::Remove(uint64 guid, bool del) if(o) { o->_SetDepleted(); + if(!del) + logdebug("ObjMgr: "I64FMT" '%s' -> depleted.",guid,o->GetName().c_str()); PseuGUI *gui = _instance->GetGUI(); if(gui) gui->NotifyObjectDeletion(guid); // we have a gui, which must delete linked DrawObject diff --git a/src/Client/World/WorldSession.cpp b/src/Client/World/WorldSession.cpp index de4da6e..c91c060 100644 --- a/src/Client/World/WorldSession.cpp +++ b/src/Client/World/WorldSession.cpp @@ -42,10 +42,9 @@ WorldSession::~WorldSession() { 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"); - 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) logdebug("~WorldSession(): ... world GUI deleted, continuing to close session"); }