Moved saved session data from UserConfig to PlayerProfile - which

means that now each player can individually save an online session.
This commit is contained in:
hiker 2014-04-09 08:33:42 +10:00
parent de697f26c8
commit 25c96d88ec
8 changed files with 145 additions and 50 deletions

View File

@ -71,32 +71,48 @@ void PlayerManager::load()
{ {
std::string filename = file_manager->getUserConfigFile("players.xml"); std::string filename = file_manager->getUserConfigFile("players.xml");
const XMLNode *players = file_manager->createXMLTree(filename); m_player_data = file_manager->createXMLTree(filename);
if(!players) if(!m_player_data)
{ {
Log::info("player_manager", "A new players.xml file will be created."); Log::info("player_manager", "A new players.xml file will be created.");
return; return;
} }
else if(players->getName()!="players") else if(m_player_data->getName()!="players")
{ {
Log::info("player_manager", "The players.xml file is invalid."); Log::info("player_manager", "The players.xml file is invalid.");
return; return;
} }
m_current_player = NULL; m_current_player = NULL;
for(unsigned int i=0; i<players->getNumNodes(); i++) for(unsigned int i=0; i<m_player_data->getNumNodes(); i++)
{ {
const XMLNode *player_xml = players->getNode(i); const XMLNode *player_xml = m_player_data->getNode(i);
PlayerProfile *player = new PlayerProfile(player_xml); PlayerProfile *player = new PlayerProfile(player_xml);
m_all_players.push_back(player); m_all_players.push_back(player);
if(player->isDefault()) if(player->isDefault())
m_current_player = player; m_current_player = player;
} }
m_all_players.insertionSort(/*start*/0, /*desc*/true);
delete players;
} // load } // load
// ----------------------------------------------------------------------------
/** The 2nd loading stage. During this stage achievements and story mode
* data is read for each player.
*/
void PlayerManager::loadRemainingData()
{
for (unsigned int i = 0; i<m_player_data->getNumNodes(); i++)
{
const XMLNode *player_xml = m_player_data->getNode(i);
m_all_players[i].loadRemainingData(player_xml);
}
delete m_player_data;
m_player_data = NULL;
// Sort player by frequency
m_all_players.insertionSort(/*start*/0, /*desc*/true);
} // loadRemainingData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Saves all player profiles to players.xml. /** Saves all player profiles to players.xml.
*/ */

View File

@ -48,6 +48,10 @@ private:
/** A pointer to the current player. */ /** A pointer to the current player. */
PlayerProfile* m_current_player; PlayerProfile* m_current_player;
/** Saves the XML tree from players.xml for use in the 2nd
* loading stage (loadRemainingData). */
const XMLNode *m_player_data;
void load(); void load();
PlayerManager(); PlayerManager();
~PlayerManager(); ~PlayerManager();
@ -72,6 +76,7 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void save(); void save();
void loadRemainingData();
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

@ -50,26 +50,52 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
} // PlayerProfile } // PlayerProfile
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Constructor to deserialize a player that was saved to a XML file. /** Constructor to deserialize player data that was saved to a XML file. The
* constructor will only load the main player data (like name, id, saved
* online data), but not the achievements and story mode data. Reason is
* that the achievement and story mode data depends on other data to be
* read first (challenges and achievement files), which in turn can only be
* created later in the startup process (they depend on e.g. all tracks to
* be known). On the other hand, automatic login needs to happen asap
* (i.e. as soon as the network thread is started), which needs the main
* player data (i.e. the default player, and saved session data). So the
* constructor only reads this data, the rest of the player data is handled
* in loadRemainingData later in the initialisation process.
* \param node The XML node representing this player. * \param node The XML node representing this player.
*/ */
PlayerProfile::PlayerProfile(const XMLNode* node) PlayerProfile::PlayerProfile(const XMLNode* node)
{ {
m_saved_session = false;
m_saved_token = "";
m_saved_user_id = 0;
m_story_mode_status = NULL;
m_achievements_status = NULL;
node->get("name", &m_name ); node->get("name", &m_name );
node->get("guest", &m_is_guest_account); node->get("guest", &m_is_guest_account);
node->get("use-frequency", &m_use_frequency ); node->get("use-frequency", &m_use_frequency );
node->get("unique-id", &m_unique_id ); node->get("unique-id", &m_unique_id );
node->get("is-default", &m_is_default ); node->get("is-default", &m_is_default );
node->get("saved-session", &m_saved_session );
node->get("saved-user", &m_saved_user_id );
node->get("saved-token", &m_saved_token );
#ifdef DEBUG #ifdef DEBUG
m_magic_number = 0xABCD1234; m_magic_number = 0xABCD1234;
#endif #endif
} // PlayerProfile
//------------------------------------------------------------------------------
/** This function loads the achievement and story mode data. This
*/
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
} // PlayerProfile
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Writes the data for this player to the specified UTFWriter. /** Writes the data for this player to the specified UTFWriter.
@ -79,9 +105,15 @@ void PlayerProfile::save(UTFWriter &out)
{ {
out << L" <player name=\"" << m_name out << L" <player name=\"" << m_name
<< L"\" guest=\"" << m_is_guest_account << L"\" guest=\"" << m_is_guest_account
<< L"\" use-frequency=\"" << m_use_frequency << L"\" use-frequency=\"" << m_use_frequency << L"\"\n";
<< L"\" is-default=\"" << m_is_default
<< L"\" unique-id=\"" << m_unique_id << L"\">\n"; out << L" is-default=\"" << m_is_default
<< L"\" unique-id=\"" << m_unique_id
<< L"\" saved-session=\"" << m_saved_session << L"\"\n";
out << L" saved-user=\"" << m_saved_user_id
<< L"\" saved-token=\"" << m_saved_token << L"\">\n";
{ {
assert(m_story_mode_status); assert(m_story_mode_status);
m_story_mode_status->save(out); m_story_mode_status->save(out);
@ -92,6 +124,31 @@ void PlayerProfile::save(UTFWriter &out)
out << L" </player>\n"; out << L" </player>\n";
} // save } // save
//------------------------------------------------------------------------------
// ------------------------------------------------------------------------
/** Saves the online data, so that it will automatically re-connect
* next time this profile is loaded.
* \param user_id Id of the online profile.
* \param token Token used for authentication.
*/
void PlayerProfile::saveSession(int user_id, const std::string &token)
{
m_saved_session = true;
m_saved_user_id = user_id;
m_saved_token = token;
PlayerManager::get()->save();
} // saveSession
// ------------------------------------------------------------------------
/** Unsets any saved session data. */
void PlayerProfile::clearSession()
{
m_saved_session = false;
m_saved_user_id = 0;
m_saved_token = "";
PlayerManager::get()->save();
} // clearSession
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Increments how often that account was used. Guest accounts are not counted. /** Increments how often that account was used. Guest accounts are not counted.
*/ */

View File

@ -62,6 +62,15 @@ private:
/** True if this is the default (last used) player. */ /** True if this is the default (last used) player. */
bool m_is_default; bool m_is_default;
/** True if this user has a saved session. */
bool m_saved_session;
/** If a session was saved, this will be the online user id to use. */
int m_saved_user_id;
/** The token of the saved session. */
std::string m_saved_token;
/** The complete challenge state. */ /** The complete challenge state. */
StoryModeStatus *m_story_mode_status; StoryModeStatus *m_story_mode_status;
@ -74,10 +83,13 @@ public:
PlayerProfile(const XMLNode *node); PlayerProfile(const XMLNode *node);
void save(UTFWriter &out); void save(UTFWriter &out);
void loadRemainingData(const XMLNode *node);
void incrementUseFrequency(); void incrementUseFrequency();
bool operator<(const PlayerProfile &other); bool operator<(const PlayerProfile &other);
bool operator>(const PlayerProfile &other); bool operator>(const PlayerProfile &other);
void raceFinished(); void raceFinished();
void saveSession(int user_id, const std::string &token);
void clearSession();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
~PlayerProfile() ~PlayerProfile()
@ -190,7 +202,24 @@ public:
{ {
return m_achievements_status; return m_achievements_status;
} // getAchievementsStatus } // getAchievementsStatus
// ------------------------------------------------------------------------
/** Returns true if a session was saved for this player. */
bool hasSavedSession() const { return m_saved_session; }
// ------------------------------------------------------------------------
/** If a session was saved, return the id of the saved user. */
int getSavedUserId() const
{
assert(m_saved_session);
return m_saved_user_id;
} // getSavedUserId
// ------------------------------------------------------------------------
/** If a session was saved, return the token to use. */
const std::string& getSavedToken() const
{
assert(m_saved_session);
return m_saved_token;
} // getSavedToken
// ------------------------------------------------------------------------
}; // class PlayerProfile }; // class PlayerProfile
#endif #endif

View File

@ -669,25 +669,6 @@ namespace UserConfigParams
&m_online_group, &m_online_group,
"The server used for online multiplayer.")); "The server used for online multiplayer."));
PARAM_PREFIX BoolUserConfigParam m_saved_session
PARAM_DEFAULT( BoolUserConfigParam( false,
"saved_session",
&m_online_group,
"Is there a saved session?") );
PARAM_PREFIX IntUserConfigParam m_saved_user
PARAM_DEFAULT( IntUserConfigParam( 0,
"saved_user",
&m_online_group,
"User ID of the saved session.") );
PARAM_PREFIX StringUserConfigParam m_saved_token
PARAM_DEFAULT( StringUserConfigParam( "",
"saved_token",
&m_online_group,
"Token of the saved session.") );
// ---- Addon server related entries // ---- Addon server related entries
PARAM_PREFIX GroupUserConfigParam m_addon_group PARAM_PREFIX GroupUserConfigParam m_addon_group
PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews", PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews",

View File

@ -1030,6 +1030,11 @@ void initRest()
addons_manager = new AddonsManager(); addons_manager = new AddonsManager();
Online::ProfileManager::create(); Online::ProfileManager::create();
// The request manager will start the login process in case of a saved
// session, so we need to read the main data from the players.xml file.
// The rest will be read later (since the rest needs the unlock- and
// achievement managers to be created, which can only be created later).
PlayerManager::create();
Online::RequestManager::get()->startNetworkThread(); Online::RequestManager::get()->startNetworkThread();
NewsManager::get(); // this will create the news manager NewsManager::get(); // this will create the news manager
@ -1165,13 +1170,15 @@ int main(int argc, char *argv[] )
handleXmasMode(); handleXmasMode();
// Needs the kart and track directories to load potential challenges // Needs the kart and track directories to load potential challenges
// in those dirs. // in those dirs, so it can only be created after reading tracks
// and karts.
unlock_manager = new UnlockManager(); unlock_manager = new UnlockManager();
AchievementsManager::create(); AchievementsManager::create();
// Needs the unlock manager to initialise the game slots of all players // Reading the rest of the player data needs the unlock manager to
// and the AchievementsManager to initialise the AchievementsStatus. // initialise the game slots of all players and the AchievementsManager
PlayerManager::create(); // to initialise the AchievementsStatus, so it is done only now.
PlayerManager::get()->loadRemainingData();
GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI, GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI,
"gui_lock.png" ) ); "gui_lock.png" ) );

View File

@ -97,14 +97,14 @@ namespace Online
void CurrentUser::requestSavedSession() void CurrentUser::requestSavedSession()
{ {
SignInRequest * request = NULL; SignInRequest * request = NULL;
if(m_state == US_SIGNED_OUT && UserConfigParams::m_saved_session) const PlayerProfile *cp = PlayerManager::getCurrentPlayer();
if (m_state == US_SIGNED_OUT && cp->hasSavedSession() )
{ {
request = new SignInRequest(true); request = new SignInRequest(true);
request->setServerURL("client-user.php"); request->setServerURL("client-user.php");
request->addParameter("action","saved-session"); request->addParameter("action","saved-session");
request->addParameter("userid", UserConfigParams::m_saved_user); request->addParameter("userid", cp->getSavedUserId());
request->addParameter("token", request->addParameter("token", cp->getSavedToken());
UserConfigParams::m_saved_token.c_str());
request->queue(); request->queue();
m_state = US_SIGNING_IN; m_state = US_SIGNING_IN;
} }
@ -179,9 +179,8 @@ namespace Online
m_state = US_SIGNED_IN; m_state = US_SIGNED_IN;
if(saveSession()) if(saveSession())
{ {
UserConfigParams::m_saved_user = getID(); PlayerManager::getCurrentPlayer()->saveSession(getID(),
UserConfigParams::m_saved_token = getToken(); getToken() );
UserConfigParams::m_saved_session = true;
} }
ProfileManager::get()->addPersistent(m_profile); ProfileManager::get()->addPersistent(m_profile);
std::string achieved_string(""); std::string achieved_string("");
@ -231,9 +230,7 @@ namespace Online
ProfileManager::get()->clearPersistent(); ProfileManager::get()->clearPersistent();
m_profile = NULL; m_profile = NULL;
m_state = US_SIGNED_OUT; m_state = US_SIGNED_OUT;
UserConfigParams::m_saved_user = 0; PlayerManager::getCurrentPlayer()->clearSession();
UserConfigParams::m_saved_token = "";
UserConfigParams::m_saved_session = false;
} // signOut } // signOut
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -102,6 +102,9 @@ namespace Online
* variable has not been assigned at that stage, and the thread might * variable has not been assigned at that stage, and the thread might
* use network_http - a very subtle race condition. So the thread can * use network_http - a very subtle race condition. So the thread can
* only be started after the assignment (in main) has been done. * only be started after the assignment (in main) has been done.
* \pre PlayerManager was created and has read the main data for each
* player so that all data for automatic login is
* availale.
*/ */
void RequestManager::startNetworkThread() void RequestManager::startNetworkThread()
{ {