Fixed #1282: STK crash on startup for the first time.

This commit is contained in:
hiker 2014-04-15 09:06:50 +10:00
parent 60a3cfb3fd
commit f33a9f7cf6
6 changed files with 63 additions and 30 deletions

View File

@ -136,21 +136,30 @@ void PlayerManager::load()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** The 2nd loading stage. During this stage achievements and story mode /** The 2nd loading stage. During this stage achievements and story mode
* data is read for each player. * data is initialised for each player. In case of existing player (i.e. not
* first time start of stk) the data is read from the players.xml file,
* in case of a first time start new/empty data structures for the players
* (which were created by default) are created.
*/ */
void PlayerManager::loadRemainingData() void PlayerManager::initRemainingData()
{ {
for (unsigned int i = 0; i<m_player_data->getNumNodes(); i++) for (unsigned int i = 0; i<m_all_players.size(); i++)
{ {
const XMLNode *player_xml = m_player_data->getNode(i); // On the first time STK is run, there is no player data,
m_all_players[i].loadRemainingData(player_xml); // so just initialise the story and achievement data
// structures
if (!m_player_data)
m_all_players[i].initRemainingData();
else // not a first time start, load remaining data
m_all_players[i].loadRemainingData(m_player_data->getNode(i));
} }
delete m_player_data; delete m_player_data;
m_player_data = NULL; m_player_data = NULL;
// Sort player by frequency // Sort player by frequency
m_all_players.insertionSort(/*start*/0, /*desc*/true); m_all_players.insertionSort(/*start*/0, /*desc*/true);
} // loadRemainingData } // initRemainingData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Saves all player profiles to players.xml. /** Saves all player profiles to players.xml.
@ -257,13 +266,13 @@ void PlayerManager::addDefaultPlayer()
else if(getenv("LOGNAME")!=NULL) // Linux, Macs else if(getenv("LOGNAME")!=NULL) // Linux, Macs
username = getenv("LOGNAME"); username = getenv("LOGNAME");
// Set the name as the default name for all players. // Set the name as the default name, but don't mark it as 'default'
// yet, since not having a default player forces the player selection
// screen to be shown.
m_all_players.push_back(new PlayerProfile(username.c_str()) ); m_all_players.push_back(new PlayerProfile(username.c_str()) );
// add default guest player // add default guest player
m_all_players.push_back( new PlayerProfile(_LTR("Guest"), /*guest*/true) ); m_all_players.push_back(new PlayerProfile(_LTR("Guest"), /*guest*/true));
} // addDefaultPlayer } // addDefaultPlayer
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -60,7 +60,7 @@ private:
PlayerProfile* m_current_player; PlayerProfile* m_current_player;
/** Saves the XML tree from players.xml for use in the 2nd /** Saves the XML tree from players.xml for use in the 2nd
* loading stage (loadRemainingData). */ * loading stage (initRemainingData). */
const XMLNode *m_player_data; const XMLNode *m_player_data;
void load(); void load();
@ -86,7 +86,7 @@ public:
} // destroy } // destroy
void save(); void save();
void loadRemainingData(); void initRemainingData();
unsigned int getUniqueId() const; unsigned int getUniqueId() const;
void addDefaultPlayer(); void addDefaultPlayer();
void addNewPlayer(const irr::core::stringw& name); void addNewPlayer(const irr::core::stringw& name);

View File

@ -41,14 +41,16 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
#endif #endif
m_name = name; m_name = name;
m_is_guest_account = is_guest; m_is_guest_account = is_guest;
m_is_default = false;
m_use_frequency = is_guest ? -1 : 0; m_use_frequency = is_guest ? -1 : 0;
m_unique_id = PlayerManager::get()->getUniqueId(); m_unique_id = PlayerManager::get()->getUniqueId();
m_story_mode_status = unlock_manager->createStoryModeStatus();
m_is_default = false;
m_current_user = new Online::CurrentUser(); m_current_user = new Online::CurrentUser();
m_achievements_status = m_is_default = false;
AchievementsManager::get()->createAchievementsStatus(); m_is_default = false;
m_saved_session = false;
m_saved_token = "";
m_saved_user_id = 0;
m_achievements_status = NULL;
m_story_mode_status = NULL;
} // PlayerProfile } // PlayerProfile
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -99,17 +101,31 @@ PlayerProfile::~PlayerProfile()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** This function loads the achievement and story mode data. This /** This function loads the achievement and story mode data. These can only
*/ * be loaded after the UnlockManager is created, which needs the karts
* and tracks to be loaded first.
*/
void PlayerProfile::loadRemainingData(const XMLNode *node) void PlayerProfile::loadRemainingData(const XMLNode *node)
{ {
const XMLNode *xml_story_mode = node->getNode("story-mode"); const XMLNode *xml_story_mode = node->getNode("story-mode");
m_story_mode_status = unlock_manager->createStoryModeStatus(xml_story_mode); m_story_mode_status =
unlock_manager->createStoryModeStatus(xml_story_mode);
const XMLNode *xml_achievements = node->getNode("achievements"); const XMLNode *xml_achievements = node->getNode("achievements");
m_achievements_status = AchievementsManager::get() m_achievements_status = AchievementsManager::get()
->createAchievementsStatus(xml_achievements); ->createAchievementsStatus(xml_achievements);
} // loadRemainingData } // initRemainingData
//------------------------------------------------------------------------------
/** Initialises the story- and achievement data structure in case of the first
* start of STK.
*/
void PlayerProfile::initRemainingData()
{
m_story_mode_status = unlock_manager->createStoryModeStatus();
m_achievements_status =
AchievementsManager::get()->createAchievementsStatus();
} // initRemainingData
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Writes the data for this player to the specified UTFWriter. /** Writes the data for this player to the specified UTFWriter.
* \param out The utf writer to write the data to. * \param out The utf writer to write the data to.
@ -128,11 +144,11 @@ void PlayerProfile::save(UTFWriter &out)
<< L"\" saved-token=\"" << m_saved_token << L"\">\n"; << L"\" saved-token=\"" << m_saved_token << L"\">\n";
{ {
assert(m_story_mode_status); if(m_story_mode_status)
m_story_mode_status->save(out); m_story_mode_status->save(out);
assert(m_achievements_status); if(m_achievements_status)
m_achievements_status->save(out); m_achievements_status->save(out);
} }
out << L" </player>\n"; out << L" </player>\n";
} // save } // save

View File

@ -86,6 +86,7 @@ public:
~PlayerProfile(); ~PlayerProfile();
void save(UTFWriter &out); void save(UTFWriter &out);
void loadRemainingData(const XMLNode *node); void loadRemainingData(const XMLNode *node);
void initRemainingData();
void incrementUseFrequency(); void incrementUseFrequency();
bool operator<(const PlayerProfile &other); bool operator<(const PlayerProfile &other);
bool operator>(const PlayerProfile &other); bool operator>(const PlayerProfile &other);

View File

@ -1178,7 +1178,7 @@ int main(int argc, char *argv[] )
// Reading the rest of the player data needs the unlock manager to // Reading the rest of the player data needs the unlock manager to
// initialise the game slots of all players and the AchievementsManager // initialise the game slots of all players and the AchievementsManager
// to initialise the AchievementsStatus, so it is done only now. // to initialise the AchievementsStatus, so it is done only now.
PlayerManager::get()->loadRemainingData(); PlayerManager::get()->initRemainingData();
GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI, GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI,
"gui_lock.png" ) ); "gui_lock.png" ) );

View File

@ -129,7 +129,10 @@ namespace Online
errno); errno);
} }
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
PlayerManager::getCurrentUser()->requestSavedSession(); // In case that login id was not saved (or first start of stk),
// current player would not be defined at this stage.
if(PlayerManager::getCurrentPlayer())
PlayerManager::getCurrentUser()->requestSavedSession();
} // startNetworkThread } // startNetworkThread
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -277,8 +280,12 @@ namespace Online
{ {
handleResultQueue(); handleResultQueue();
//Database polling starts here, only needed for registered users // Database polling starts here, only needed for registered users. If
if (!PlayerManager::isCurrentLoggedIn()) // there is no player data yet (i.e. either because first time start
// of stk, and loging screen hasn't finished yet, or no default player
// was saved), don't do anything
if (!PlayerManager::getCurrentPlayer() ||
!PlayerManager::isCurrentLoggedIn())
return; return;
m_time_since_poll += dt; m_time_since_poll += dt;