1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-07-10 04:41:35 +00:00

Change CharacterManager to use list instead of vector

Solves a crash when deleting all savegames of a character due to mCurrent being invalidated
This commit is contained in:
scrawl 2014-06-02 20:24:35 +02:00
parent 68afac6a19
commit 996e49c534
3 changed files with 32 additions and 20 deletions

View file

@ -1,7 +1,7 @@
#ifndef GAME_MWSTATE_STATEMANAGER_H #ifndef GAME_MWSTATE_STATEMANAGER_H
#define GAME_MWSTATE_STATEMANAGER_H #define GAME_MWSTATE_STATEMANAGER_H
#include <vector> #include <list>
#include <string> #include <string>
namespace MWState namespace MWState
@ -24,7 +24,7 @@ namespace MWBase
State_Running State_Running
}; };
typedef std::vector<MWState::Character>::const_iterator CharacterIterator; typedef std::list<MWState::Character>::const_iterator CharacterIterator;
private: private:

View file

@ -49,20 +49,17 @@ MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create)
void MWState::CharacterManager::deleteSlot(const MWState::Character *character, const MWState::Slot *slot) void MWState::CharacterManager::deleteSlot(const MWState::Character *character, const MWState::Slot *slot)
{ {
int index = character - &mCharacters[0]; std::list<Character>::iterator it = findCharacter(character);
if (index<0 || index>=static_cast<int> (mCharacters.size())) it->deleteSlot(slot);
throw std::logic_error ("invalid character");
mCharacters[index].deleteSlot(slot); if (character->begin() == character->end())
if (mCharacters[index].begin() == mCharacters[index].end())
{ {
// All slots deleted, cleanup and remove this character // All slots deleted, cleanup and remove this character
mCharacters[index].cleanup(); it->cleanup();
if (character == mCurrent) if (character == mCurrent)
mCurrent = NULL; mCurrent = NULL;
mCharacters.erase(mCharacters.begin() + index); mCharacters.erase(it);
} }
} }
@ -78,14 +75,24 @@ void MWState::CharacterManager::createCharacter()
mCurrent = &mCharacters.back(); mCurrent = &mCharacters.back();
} }
std::list<MWState::Character>::iterator MWState::CharacterManager::findCharacter(const MWState::Character* character)
{
std::list<Character>::iterator it = mCharacters.begin();
for (; it != mCharacters.end(); ++it)
{
if (&*it == character)
break;
}
if (it == mCharacters.end())
throw std::logic_error ("invalid character");
return it;
}
void MWState::CharacterManager::setCurrentCharacter (const Character *character) void MWState::CharacterManager::setCurrentCharacter (const Character *character)
{ {
int index = character - &mCharacters[0]; std::list<Character>::iterator it = findCharacter(character);
if (index<0 || index>=static_cast<int> (mCharacters.size())) mCurrent = &*it;
throw std::logic_error ("invalid character");
mCurrent = &mCharacters[index];
} }
void MWState::CharacterManager::clearCurrentCharacter() void MWState::CharacterManager::clearCurrentCharacter()
@ -93,12 +100,12 @@ void MWState::CharacterManager::clearCurrentCharacter()
mCurrent = 0; mCurrent = 0;
} }
std::vector<MWState::Character>::const_iterator MWState::CharacterManager::begin() const std::list<MWState::Character>::const_iterator MWState::CharacterManager::begin() const
{ {
return mCharacters.begin(); return mCharacters.begin();
} }
std::vector<MWState::Character>::const_iterator MWState::CharacterManager::end() const std::list<MWState::Character>::const_iterator MWState::CharacterManager::end() const
{ {
return mCharacters.end(); return mCharacters.end();
} }

View file

@ -11,7 +11,10 @@ namespace MWState
{ {
boost::filesystem::path mPath; boost::filesystem::path mPath;
int mNext; int mNext;
std::vector<Character> mCharacters;
// Uses std::list, so that mCurrent stays valid when characters are deleted
std::list<Character> mCharacters;
Character *mCurrent; Character *mCurrent;
std::string mGame; std::string mGame;
@ -23,6 +26,8 @@ namespace MWState
CharacterManager& operator= (const CharacterManager&); CharacterManager& operator= (const CharacterManager&);
///< Not implemented ///< Not implemented
std::list<Character>::iterator findCharacter(const MWState::Character* character);
public: public:
CharacterManager (const boost::filesystem::path& saves, const std::string& game); CharacterManager (const boost::filesystem::path& saves, const std::string& game);
@ -39,9 +44,9 @@ namespace MWState
void clearCurrentCharacter(); void clearCurrentCharacter();
std::vector<Character>::const_iterator begin() const; std::list<Character>::const_iterator begin() const;
std::vector<Character>::const_iterator end() const; std::list<Character>::const_iterator end() const;
}; };
} }