mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-02 02:06:42 +00:00
Use descriptive names for save files and character folders (Fixes #1449)
This commit is contained in:
parent
e796fa2313
commit
7721e54191
5 changed files with 58 additions and 31 deletions
|
@ -54,9 +54,28 @@ void MWState::Character::addSlot (const ESM::SavedGame& profile)
|
||||||
Slot slot;
|
Slot slot;
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << mNext++;
|
|
||||||
|
// The profile description is user-supplied, so we need to escape the path
|
||||||
|
for (std::string::const_iterator it = profile.mDescription.begin(); it != profile.mDescription.end(); ++it)
|
||||||
|
{
|
||||||
|
if (std::isalnum(*it)) // Ignores multibyte characters and non alphanumeric characters
|
||||||
|
stream << *it;
|
||||||
|
else
|
||||||
|
stream << "_";
|
||||||
|
}
|
||||||
|
|
||||||
slot.mPath = mPath / stream.str();
|
slot.mPath = mPath / stream.str();
|
||||||
|
|
||||||
|
// Append an index if necessary to ensure a unique file
|
||||||
|
int i=0;
|
||||||
|
while (boost::filesystem::exists(slot.mPath))
|
||||||
|
{
|
||||||
|
std::ostringstream test;
|
||||||
|
test << stream.str();
|
||||||
|
test << " - " << ++i;
|
||||||
|
slot.mPath = mPath / test.str();
|
||||||
|
}
|
||||||
|
|
||||||
slot.mProfile = profile;
|
slot.mProfile = profile;
|
||||||
slot.mTimeStamp = std::time (0);
|
slot.mTimeStamp = std::time (0);
|
||||||
|
|
||||||
|
@ -64,7 +83,7 @@ void MWState::Character::addSlot (const ESM::SavedGame& profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
MWState::Character::Character (const boost::filesystem::path& saves, const std::string& game)
|
MWState::Character::Character (const boost::filesystem::path& saves, const std::string& game)
|
||||||
: mPath (saves), mNext (0)
|
: mPath (saves)
|
||||||
{
|
{
|
||||||
if (!boost::filesystem::is_directory (mPath))
|
if (!boost::filesystem::is_directory (mPath))
|
||||||
{
|
{
|
||||||
|
@ -82,13 +101,6 @@ MWState::Character::Character (const boost::filesystem::path& saves, const std::
|
||||||
addSlot (slotPath, game);
|
addSlot (slotPath, game);
|
||||||
}
|
}
|
||||||
catch (...) {} // ignoring bad saved game files for now
|
catch (...) {} // ignoring bad saved game files for now
|
||||||
|
|
||||||
std::istringstream stream (slotPath.filename().string());
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if ((stream >> index) && index>=mNext)
|
|
||||||
mNext = index+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort (mSlots.begin(), mSlots.end());
|
std::sort (mSlots.begin(), mSlots.end());
|
||||||
|
|
|
@ -26,7 +26,6 @@ namespace MWState
|
||||||
|
|
||||||
boost::filesystem::path mPath;
|
boost::filesystem::path mPath;
|
||||||
std::vector<Slot> mSlots;
|
std::vector<Slot> mSlots;
|
||||||
int mNext;
|
|
||||||
|
|
||||||
void addSlot (const boost::filesystem::path& path, const std::string& game);
|
void addSlot (const boost::filesystem::path& path, const std::string& game);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
MWState::CharacterManager::CharacterManager (const boost::filesystem::path& saves,
|
MWState::CharacterManager::CharacterManager (const boost::filesystem::path& saves,
|
||||||
const std::string& game)
|
const std::string& game)
|
||||||
: mPath (saves), mNext (0), mCurrent (0), mGame (game)
|
: mPath (saves), mCurrent (0), mGame (game)
|
||||||
{
|
{
|
||||||
if (!boost::filesystem::is_directory (mPath))
|
if (!boost::filesystem::is_directory (mPath))
|
||||||
{
|
{
|
||||||
|
@ -28,21 +28,14 @@ MWState::CharacterManager::CharacterManager (const boost::filesystem::path& save
|
||||||
if (character.begin()!=character.end())
|
if (character.begin()!=character.end())
|
||||||
mCharacters.push_back (character);
|
mCharacters.push_back (character);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::istringstream stream (characterDir.filename().string());
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if ((stream >> index) && index>=mNext)
|
|
||||||
mNext = index+1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create)
|
MWState::Character *MWState::CharacterManager::getCurrentCharacter (bool create, const std::string& name)
|
||||||
{
|
{
|
||||||
if (!mCurrent && create)
|
if (!mCurrent && create)
|
||||||
createCharacter();
|
createCharacter(name);
|
||||||
|
|
||||||
return mCurrent;
|
return mCurrent;
|
||||||
}
|
}
|
||||||
|
@ -63,13 +56,31 @@ void MWState::CharacterManager::deleteSlot(const MWState::Character *character,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWState::CharacterManager::createCharacter()
|
void MWState::CharacterManager::createCharacter(const std::string& name)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << mNext++;
|
|
||||||
|
// The character name is user-supplied, so we need to escape the path
|
||||||
|
for (std::string::const_iterator it = name.begin(); it != name.end(); ++it)
|
||||||
|
{
|
||||||
|
if (std::isalnum(*it)) // Ignores multibyte characters and non alphanumeric characters
|
||||||
|
stream << *it;
|
||||||
|
else
|
||||||
|
stream << "_";
|
||||||
|
}
|
||||||
|
|
||||||
boost::filesystem::path path = mPath / stream.str();
|
boost::filesystem::path path = mPath / stream.str();
|
||||||
|
|
||||||
|
// Append an index if necessary to ensure a unique directory
|
||||||
|
int i=0;
|
||||||
|
while (boost::filesystem::exists(path))
|
||||||
|
{
|
||||||
|
std::ostringstream test;
|
||||||
|
test << stream.str();
|
||||||
|
test << " - " << ++i;
|
||||||
|
path = mPath / test.str();
|
||||||
|
}
|
||||||
|
|
||||||
mCharacters.push_back (Character (path, mGame));
|
mCharacters.push_back (Character (path, mGame));
|
||||||
|
|
||||||
mCurrent = &mCharacters.back();
|
mCurrent = &mCharacters.back();
|
||||||
|
|
|
@ -10,7 +10,6 @@ namespace MWState
|
||||||
class CharacterManager
|
class CharacterManager
|
||||||
{
|
{
|
||||||
boost::filesystem::path mPath;
|
boost::filesystem::path mPath;
|
||||||
int mNext;
|
|
||||||
|
|
||||||
// Uses std::list, so that mCurrent stays valid when characters are deleted
|
// Uses std::list, so that mCurrent stays valid when characters are deleted
|
||||||
std::list<Character> mCharacters;
|
std::list<Character> mCharacters;
|
||||||
|
@ -32,13 +31,15 @@ namespace MWState
|
||||||
|
|
||||||
CharacterManager (const boost::filesystem::path& saves, const std::string& game);
|
CharacterManager (const boost::filesystem::path& saves, const std::string& game);
|
||||||
|
|
||||||
Character *getCurrentCharacter (bool create = true);
|
Character *getCurrentCharacter (bool create, const std::string& name);
|
||||||
///< \param create Create a new character, if there is no current character.
|
///< \param create Create a new character, if there is no current character.
|
||||||
|
/// \param name The character name to use in case a new character is created.
|
||||||
|
|
||||||
void deleteSlot(const MWState::Character *character, const MWState::Slot *slot);
|
void deleteSlot(const MWState::Character *character, const MWState::Slot *slot);
|
||||||
|
|
||||||
void createCharacter();
|
void createCharacter(const std::string& name);
|
||||||
///< Create new character within saved game management
|
///< Create new character within saved game management
|
||||||
|
/// \param name Name for the character (does not need to be unique)
|
||||||
|
|
||||||
void setCurrentCharacter (const Character *character);
|
void setCurrentCharacter (const Character *character);
|
||||||
|
|
||||||
|
|
|
@ -184,9 +184,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
encoded->read(&profile.mScreenshot[0], encoded->size());
|
encoded->read(&profile.mScreenshot[0], encoded->size());
|
||||||
|
|
||||||
if (!slot)
|
if (!slot)
|
||||||
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
|
slot = getCurrentCharacter()->createSlot (profile);
|
||||||
else
|
else
|
||||||
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
|
slot = getCurrentCharacter()->updateSlot (slot, profile);
|
||||||
|
|
||||||
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
|
boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
|
|
||||||
// If no file was written, clean up the slot
|
// If no file was written, clean up the slot
|
||||||
if (slot && !boost::filesystem::exists(slot->mPath))
|
if (slot && !boost::filesystem::exists(slot->mPath))
|
||||||
mCharacterManager.getCurrentCharacter()->deleteSlot(slot);
|
getCurrentCharacter()->deleteSlot(slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,10 @@ void MWState::StateManager::deleteGame(const MWState::Character *character, cons
|
||||||
|
|
||||||
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
|
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
|
||||||
{
|
{
|
||||||
return mCharacterManager.getCurrentCharacter (create);
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
std::string name = player.getClass().getName(player);
|
||||||
|
|
||||||
|
return mCharacterManager.getCurrentCharacter (create, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWState::StateManager::CharacterIterator MWState::StateManager::characterBegin()
|
MWState::StateManager::CharacterIterator MWState::StateManager::characterBegin()
|
||||||
|
@ -440,11 +443,12 @@ void MWState::StateManager::update (float duration)
|
||||||
if (mAskLoadRecent)
|
if (mAskLoadRecent)
|
||||||
{
|
{
|
||||||
int iButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
|
int iButton = MWBase::Environment::get().getWindowManager()->readPressedButton();
|
||||||
if(iButton==0)
|
MWState::Character *curCharacter = getCurrentCharacter(false);
|
||||||
|
if(iButton==0 && curCharacter)
|
||||||
{
|
{
|
||||||
mAskLoadRecent = false;
|
mAskLoadRecent = false;
|
||||||
//Load last saved game for current character
|
//Load last saved game for current character
|
||||||
MWState::Character *curCharacter = getCurrentCharacter();
|
|
||||||
MWState::Slot lastSave = *curCharacter->begin();
|
MWState::Slot lastSave = *curCharacter->begin();
|
||||||
loadGame(curCharacter, &lastSave);
|
loadGame(curCharacter, &lastSave);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue