Compare commits
16 Commits
master
...
steam-test
Author | SHA1 | Date | |
---|---|---|---|
|
90f4855938 | ||
|
9d350ebaa6 | ||
|
059b77d34b | ||
|
31f970f625 | ||
|
d651e0c710 | ||
|
b0408d414c | ||
|
dddd00142b | ||
|
01aeb9f2fd | ||
|
29e1541b47 | ||
|
92709b2ada | ||
|
ffca9b14d8 | ||
|
bff3989bfc | ||
|
1d7aa7a2f5 | ||
|
de795b766a | ||
|
eb4989c2ef | ||
|
9760826252 |
@ -14,6 +14,12 @@
|
|||||||
|
|
||||||
<spacer height="15" width="10"/>
|
<spacer height="15" width="10"/>
|
||||||
<div width="90%" align="center" layout="vertical-row" proportion="1">
|
<div width="90%" align="center" layout="vertical-row" proportion="1">
|
||||||
|
<div width="100%" height="fit" layout="horizontal-row" >
|
||||||
|
<checkbox width="fit" id="steam" I18N="In the user screen" text_align="left"/>
|
||||||
|
<spacer width="10"/>
|
||||||
|
<label proportion="1" id="label-steam" height="100%" text_align="left"
|
||||||
|
I18N="In the user screen" text="Is a Steam account"/>
|
||||||
|
</div>
|
||||||
<div width="100%" height="fit" layout="horizontal-row" >
|
<div width="100%" height="fit" layout="horizontal-row" >
|
||||||
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
|
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
|
||||||
<spacer width="10"/>
|
<spacer width="10"/>
|
||||||
|
@ -23,6 +23,12 @@
|
|||||||
|
|
||||||
<spacer height="15" width="10"/>
|
<spacer height="15" width="10"/>
|
||||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||||
|
<div width="100%" height="fit" layout="horizontal-row" >
|
||||||
|
<checkbox width="fit" id="steam" I18N="In the user screen" text_align="left"/>
|
||||||
|
<spacer width="10"/>
|
||||||
|
<label proportion="1" id="label-steam" height="100%" text_align="left"
|
||||||
|
I18N="In the user screen" text="Is a Steam account"/>
|
||||||
|
</div>
|
||||||
<div width="100%" height="fit" layout="horizontal-row" >
|
<div width="100%" height="fit" layout="horizontal-row" >
|
||||||
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
|
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
|
||||||
<spacer width="10"/>
|
<spacer width="10"/>
|
||||||
|
@ -162,6 +162,11 @@
|
|||||||
work anymore - so for now don't enable this. -->
|
work anymore - so for now don't enable this. -->
|
||||||
<networking enable="false"/>
|
<networking enable="false"/>
|
||||||
|
|
||||||
|
<!-- Steam related settings:
|
||||||
|
ask-for-internet - If true the user on first start will be asked
|
||||||
|
for permission to connect to stk servers. -->
|
||||||
|
<steam ask-for-internet="false"/>
|
||||||
|
|
||||||
<!-- The field od views for 1-4 player split screen. fov-3 is
|
<!-- The field od views for 1-4 player split screen. fov-3 is
|
||||||
actually not used (since 3 player split screen uses the
|
actually not used (since 3 player split screen uses the
|
||||||
same layout as 4 player split screen) -->
|
same layout as 4 player split screen) -->
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "io/utf_writer.hpp"
|
#include "io/utf_writer.hpp"
|
||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
#include "online/online_player_profile.hpp"
|
#include "online/online_player_profile.hpp"
|
||||||
|
#include "online/steam.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
#include "utils/translation.hpp"
|
#include "utils/translation.hpp"
|
||||||
|
|
||||||
@ -209,17 +210,126 @@ void PlayerManager::load()
|
|||||||
PlayerProfile *player = new Online::OnlinePlayerProfile(player_xml);
|
PlayerProfile *player = new Online::OnlinePlayerProfile(player_xml);
|
||||||
m_all_players.push_back(player);
|
m_all_players.push_back(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_player = NULL;
|
m_current_player = NULL;
|
||||||
const XMLNode *current = m_player_data->getNode("current");
|
const XMLNode *current = m_player_data->getNode("current");
|
||||||
|
stringw current_name;
|
||||||
|
|
||||||
if (current)
|
if (current)
|
||||||
{
|
{
|
||||||
stringw name;
|
current->getAndDecode("player", ¤t_name);
|
||||||
current->getAndDecode("player", &name);
|
|
||||||
m_current_player = getPlayer(name);
|
|
||||||
}
|
}
|
||||||
|
if (!checkSteamAccount(current_name))
|
||||||
|
{
|
||||||
|
m_current_player = getPlayer(current_name);
|
||||||
|
} // if current
|
||||||
|
|
||||||
} // load
|
} // load
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** This functions checks if a stk user exists with the same steam id as the
|
||||||
|
* current steam user, and if so switches to that player (ignoring that stk
|
||||||
|
* might have a different 'current' player). If no stk account with same
|
||||||
|
* steam id is found, it then also checks if a non-steam stk account with the
|
||||||
|
* same name (case independent) exists, and if so, switches that account
|
||||||
|
* to be connect to the current steam user.
|
||||||
|
* If no matching stk account can be found, do nothing - the user then would
|
||||||
|
* have to rename an existing account or create a new account to be connected
|
||||||
|
* to the steam id.
|
||||||
|
* \return True if a matching steam account was found (which means that the
|
||||||
|
* current user in stk is ignored).
|
||||||
|
*/
|
||||||
|
bool PlayerManager::checkSteamAccount(const irr::core::stringw ¤t_name)
|
||||||
|
{
|
||||||
|
if (!Steam::get()->isSteamAvailable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// First check for an stk account with same steam id:
|
||||||
|
const stringw &steam_name = Steam::get()->getUserNameWchar();
|
||||||
|
const std::string &steam_id = Steam::get()->getSteamID();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < m_all_players.size(); i++)
|
||||||
|
{
|
||||||
|
if (m_all_players[i].isSteamUser() &&
|
||||||
|
m_all_players[i].getSteamUserID() == steam_id)
|
||||||
|
{
|
||||||
|
// Check if the previously (current) name is different from
|
||||||
|
// the steam name, and if so print a warning, but continue
|
||||||
|
// with switching to the correct steam user id.
|
||||||
|
if (!current_name.equals_ignore_case(steam_name))
|
||||||
|
{
|
||||||
|
Log::warn("PlayerManager",
|
||||||
|
"Switching from previous user '%ls' to '%ls'.",
|
||||||
|
current_name.c_str(), steam_name.c_str() );
|
||||||
|
} // if steam and current name are different
|
||||||
|
|
||||||
|
m_current_player = getPlayer(i);
|
||||||
|
// Update the steam name in case that the user did a rename
|
||||||
|
m_current_player->setToCurrentSteamUser();
|
||||||
|
return true;
|
||||||
|
} // same steam user id
|
||||||
|
} // for i in m_all_players
|
||||||
|
|
||||||
|
// Now check for an existing account name that matches the steam name.
|
||||||
|
// This is only done on the first time an STK version is running that
|
||||||
|
// connects to steam. From then on the user must go to the user screen
|
||||||
|
// to connect or disconnect STK accounts to steam accounts.
|
||||||
|
if (UserConfigParams::m_steam_first_start)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < m_all_players.size(); i++)
|
||||||
|
{
|
||||||
|
// Ignore existing steam users, they must have a different id
|
||||||
|
// (otherwise they would have been picked in the previous loop)
|
||||||
|
if (m_all_players[i].isSteamUser()) continue;
|
||||||
|
stringw name = m_all_players[i].getName();
|
||||||
|
if (name.equals_ignore_case(steam_name))
|
||||||
|
{
|
||||||
|
Log::warn("PlayerManager",
|
||||||
|
"Connecting '%ls' to current steam account '%ls'.",
|
||||||
|
current_name.c_str(), steam_name.c_str());
|
||||||
|
|
||||||
|
m_current_player = getPlayer(i);
|
||||||
|
m_current_player->setToCurrentSteamUser();
|
||||||
|
return true;
|
||||||
|
} // if steam and current name are different
|
||||||
|
} // for i in m_all_players
|
||||||
|
|
||||||
|
// No matching existing user found. Last try: if there is only
|
||||||
|
// one stk account, connect it to the current steam account:
|
||||||
|
if (m_all_players.size() == 1)
|
||||||
|
{
|
||||||
|
m_current_player = getPlayer(0);
|
||||||
|
m_current_player->setToCurrentSteamUser();
|
||||||
|
Log::warn("PlayerManager",
|
||||||
|
"Connecting only account '%ls' to current steam account '%ls'.",
|
||||||
|
m_current_player->getName().c_str(), steam_name.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // If first time steam version is started.
|
||||||
|
|
||||||
|
// Otherwise now current user is NULL: if this is the first time that
|
||||||
|
// stk starts under steam (and an stk account existed, otherwise this
|
||||||
|
// function is not called), main() will bring up the user login screen
|
||||||
|
// where the user can connect and disconnect stk- and steam-accounts.
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // checkSteamAccount
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Disconnects all account(s) that uses the given steam id from steam.
|
||||||
|
*/
|
||||||
|
void PlayerManager::disconnectSteamAccount(const std::string &steam_id)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < m_all_players.size(); i++)
|
||||||
|
{
|
||||||
|
PlayerProfile &player = m_all_players[i];
|
||||||
|
if (player.isSteamUser() && player.getSteamUserID() == steam_id)
|
||||||
|
{
|
||||||
|
player.clearSteamData();
|
||||||
|
} // if right steam user
|
||||||
|
} // for i in m_all_players
|
||||||
|
} // disconnectSteamAccount
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** The 2nd loading stage. During this stage achievements and story mode
|
/** The 2nd loading stage. During this stage achievements and story mode
|
||||||
* data is initialised for each player. In case of existing player (i.e. not
|
* data is initialised for each player. In case of existing player (i.e. not
|
||||||
|
@ -66,6 +66,7 @@ private:
|
|||||||
const XMLNode *m_player_data;
|
const XMLNode *m_player_data;
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
|
bool checkSteamAccount(const irr::core::stringw ¤t_name);
|
||||||
PlayerManager();
|
PlayerManager();
|
||||||
~PlayerManager();
|
~PlayerManager();
|
||||||
|
|
||||||
@ -101,6 +102,8 @@ public:
|
|||||||
static void setUserDetails(Online::HTTPRequest *request,
|
static void setUserDetails(Online::HTTPRequest *request,
|
||||||
const std::string &action,
|
const std::string &action,
|
||||||
const std::string &php_name = "");
|
const std::string &php_name = "");
|
||||||
|
void disconnectSteamAccount(const std::string &steam_id);
|
||||||
|
|
||||||
static unsigned int getCurrentOnlineId();
|
static unsigned int getCurrentOnlineId();
|
||||||
static bool isCurrentLoggedIn();
|
static bool isCurrentLoggedIn();
|
||||||
static Online::OnlineProfile* getCurrentOnlineProfile();
|
static Online::OnlineProfile* getCurrentOnlineProfile();
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "karts/kart_properties.hpp"
|
#include "karts/kart_properties.hpp"
|
||||||
#include "karts/kart_properties_manager.hpp"
|
#include "karts/kart_properties_manager.hpp"
|
||||||
#include "online/online_player_profile.hpp"
|
#include "online/online_player_profile.hpp"
|
||||||
|
#include "online/steam.hpp"
|
||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
#include "io/utf_writer.hpp"
|
#include "io/utf_writer.hpp"
|
||||||
#include "utils/string_utils.hpp"
|
#include "utils/string_utils.hpp"
|
||||||
@ -38,6 +39,17 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
m_magic_number = 0xABCD1234;
|
m_magic_number = 0xABCD1234;
|
||||||
#endif
|
#endif
|
||||||
|
if(Steam::get()->isSteamAvailable() &&
|
||||||
|
name == Steam::get()->getUserNameWchar() )
|
||||||
|
{
|
||||||
|
m_steam_id = Steam::get()->getSteamID();
|
||||||
|
m_steam_name = Steam::get()->getUserNameWchar();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_steam_id = "";
|
||||||
|
m_steam_name = "";
|
||||||
|
}
|
||||||
m_local_name = name;
|
m_local_name = name;
|
||||||
m_is_guest_account = is_guest;
|
m_is_guest_account = is_guest;
|
||||||
m_use_frequency = is_guest ? -1 : 0;
|
m_use_frequency = is_guest ? -1 : 0;
|
||||||
@ -68,6 +80,8 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
|
|||||||
*/
|
*/
|
||||||
PlayerProfile::PlayerProfile(const XMLNode* node)
|
PlayerProfile::PlayerProfile(const XMLNode* node)
|
||||||
{
|
{
|
||||||
|
m_steam_id = "";
|
||||||
|
m_steam_name = "";
|
||||||
m_saved_session = false;
|
m_saved_session = false;
|
||||||
m_saved_token = "";
|
m_saved_token = "";
|
||||||
m_saved_user_id = 0;
|
m_saved_user_id = 0;
|
||||||
@ -79,6 +93,8 @@ PlayerProfile::PlayerProfile(const XMLNode* node)
|
|||||||
m_icon_filename = "";
|
m_icon_filename = "";
|
||||||
|
|
||||||
node->getAndDecode("name", &m_local_name );
|
node->getAndDecode("name", &m_local_name );
|
||||||
|
node->get("steam-id", &m_steam_id );
|
||||||
|
node->get("steam-name", &m_steam_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 );
|
||||||
@ -154,6 +170,23 @@ void PlayerProfile::addIcon()
|
|||||||
if (m_icon_filename.size() > 0 || isGuestAccount())
|
if (m_icon_filename.size() > 0 || isGuestAccount())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (isSteamUser())
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << m_unique_id << ".png";
|
||||||
|
std::string full_path = file_manager->getUserConfigFile(out.str());
|
||||||
|
Steam::get()->saveAvatarAs(full_path);
|
||||||
|
if (file_manager->fileExists(full_path))
|
||||||
|
{
|
||||||
|
m_icon_filename = out.str();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_icon_filename = "";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int n = (m_unique_id + kart_properties_manager->getKartId("tux") - 1)
|
int n = (m_unique_id + kart_properties_manager->getKartId("tux") - 1)
|
||||||
% kart_properties_manager->getNumberOfKarts();
|
% kart_properties_manager->getNumberOfKarts();
|
||||||
|
|
||||||
@ -202,6 +235,9 @@ void PlayerProfile::save(UTFWriter &out)
|
|||||||
<< L"\" guest=\"" << m_is_guest_account
|
<< L"\" guest=\"" << m_is_guest_account
|
||||||
<< L"\" use-frequency=\"" << m_use_frequency << L"\"\n";
|
<< L"\" use-frequency=\"" << m_use_frequency << L"\"\n";
|
||||||
|
|
||||||
|
out << L" steam-id=\"" << m_steam_id
|
||||||
|
<< L"\" steam-name=\"" << m_steam_name << L"\"\n";
|
||||||
|
|
||||||
out << L" icon-filename=\"" << m_icon_filename << L"\"\n";
|
out << L" icon-filename=\"" << m_icon_filename << L"\"\n";
|
||||||
|
|
||||||
out << L" unique-id=\"" << m_unique_id
|
out << L" unique-id=\"" << m_unique_id
|
||||||
@ -266,6 +302,30 @@ void PlayerProfile::raceFinished()
|
|||||||
m_achievements_status->onRaceEnd();
|
m_achievements_status->onRaceEnd();
|
||||||
} // raceFinished
|
} // raceFinished
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/** Connects this user to the currently logged in Steam account. It saves the
|
||||||
|
* unique steam id and the (not necessarily unique) steam user name.
|
||||||
|
*/
|
||||||
|
void PlayerProfile::setToCurrentSteamUser()
|
||||||
|
{
|
||||||
|
if (!Steam::get()->isSteamAvailable())
|
||||||
|
{
|
||||||
|
Log::error("PlayerProfile",
|
||||||
|
"Can not set to current steam user, steam is not available.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_steam_id = Steam::get()->getSteamID();
|
||||||
|
m_steam_name = Steam::get()->getUserNameWchar();
|
||||||
|
} // setToCurrentSteamUser
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/** Disconnects this player from its steam account.
|
||||||
|
*/
|
||||||
|
void PlayerProfile::clearSteamData()
|
||||||
|
{
|
||||||
|
m_steam_id = "";
|
||||||
|
m_steam_name = "";
|
||||||
|
} // clearSteamData
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/** Comparison used to sort players.
|
/** Comparison used to sort players.
|
||||||
*/
|
*/
|
||||||
|
@ -97,6 +97,15 @@ private:
|
|||||||
/** The token of the saved session. */
|
/** The token of the saved session. */
|
||||||
std::string m_saved_token;
|
std::string m_saved_token;
|
||||||
|
|
||||||
|
/** If the account is a steam account, this stores the steam user id.
|
||||||
|
* Otherwise it is empty. A steam account can only be selected if
|
||||||
|
* the user is logged into steam! */
|
||||||
|
std::string m_steam_id;
|
||||||
|
|
||||||
|
/** Name of the corresponding steam account. Empty if this is
|
||||||
|
* not a steam account. */
|
||||||
|
core::stringw m_steam_name;
|
||||||
|
|
||||||
/** The online user name used last (empty if not used online). */
|
/** The online user name used last (empty if not used online). */
|
||||||
core::stringw m_last_online_name;
|
core::stringw m_last_online_name;
|
||||||
|
|
||||||
@ -125,6 +134,8 @@ public:
|
|||||||
void saveSession(int user_id, const std::string &token);
|
void saveSession(int user_id, const std::string &token);
|
||||||
void clearSession(bool save=true);
|
void clearSession(bool save=true);
|
||||||
void addIcon();
|
void addIcon();
|
||||||
|
void setToCurrentSteamUser();
|
||||||
|
void clearSteamData();
|
||||||
|
|
||||||
/** Abstract virtual classes, to be implemented by the OnlinePlayer. */
|
/** Abstract virtual classes, to be implemented by the OnlinePlayer. */
|
||||||
virtual void setUserDetails(Online::HTTPRequest *request,
|
virtual void setUserDetails(Online::HTTPRequest *request,
|
||||||
@ -300,6 +311,16 @@ public:
|
|||||||
/** Sets if this player was logged in last time it was used. */
|
/** Sets if this player was logged in last time it was used. */
|
||||||
void setRememberPassword(bool b) { m_remember_password = b; }
|
void setRememberPassword(bool b) { m_remember_password = b; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns if this account is a steam account. */
|
||||||
|
bool isSteamUser() const { return m_steam_id != ""; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the steam user id of this player ("" if not a steam account).*/
|
||||||
|
const std::string &getSteamUserID() const { return m_steam_id; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the steam name of the connected steam account (or "" if
|
||||||
|
* this account is not a steam account. */
|
||||||
|
const core::stringw &getSteamName() const { return m_steam_name; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
}; // class PlayerProfile
|
}; // class PlayerProfile
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -181,6 +181,7 @@ void STKConfig::init_defaults()
|
|||||||
m_disable_steer_while_unskid = false;
|
m_disable_steer_while_unskid = false;
|
||||||
m_camera_follow_skid = false;
|
m_camera_follow_skid = false;
|
||||||
m_cutscene_fov = 0.61f;
|
m_cutscene_fov = 0.61f;
|
||||||
|
m_steam_ask_for_internet = false;
|
||||||
|
|
||||||
m_score_increase.clear();
|
m_score_increase.clear();
|
||||||
m_leader_intervals.clear();
|
m_leader_intervals.clear();
|
||||||
@ -274,6 +275,11 @@ void STKConfig::getAllData(const XMLNode * root)
|
|||||||
camera->get("cutscene-fov", &m_cutscene_fov);
|
camera->get("cutscene-fov", &m_cutscene_fov);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const XMLNode *steam = root->getNode("steam"))
|
||||||
|
{
|
||||||
|
steam->get("ask-for-internet", &m_steam_ask_for_internet);
|
||||||
|
}
|
||||||
|
|
||||||
if (const XMLNode *music_node = root->getNode("music"))
|
if (const XMLNode *music_node = root->getNode("music"))
|
||||||
{
|
{
|
||||||
std::string title_music;
|
std::string title_music;
|
||||||
|
@ -152,6 +152,10 @@ public:
|
|||||||
|
|
||||||
float m_cutscene_fov;
|
float m_cutscene_fov;
|
||||||
|
|
||||||
|
/** True if the internet question should still be asked when
|
||||||
|
* a steam connection is make. */
|
||||||
|
bool m_steam_ask_for_internet;
|
||||||
|
|
||||||
/** Lists of TTF files used in STK. */
|
/** Lists of TTF files used in STK. */
|
||||||
std::vector<std::string> m_normal_ttf;
|
std::vector<std::string> m_normal_ttf;
|
||||||
std::vector<std::string> m_digit_ttf;
|
std::vector<std::string> m_digit_ttf;
|
||||||
|
@ -914,6 +914,16 @@ namespace UserConfigParams
|
|||||||
&m_online_group,
|
&m_online_group,
|
||||||
"Version of the server API to use."));
|
"Version of the server API to use."));
|
||||||
|
|
||||||
|
// ---- Online gameplay related
|
||||||
|
PARAM_PREFIX GroupUserConfigParam m_steam_group
|
||||||
|
PARAM_DEFAULT(GroupUserConfigParam("Steam",
|
||||||
|
"Everything related to steam."));
|
||||||
|
|
||||||
|
PARAM_PREFIX BoolUserConfigParam m_steam_first_start
|
||||||
|
PARAM_DEFAULT(BoolUserConfigParam(true,
|
||||||
|
"steam-first-start",
|
||||||
|
&m_steam_group,
|
||||||
|
"If this is the first time the STK steam version was started"));
|
||||||
|
|
||||||
// ---- Addon server related entries
|
// ---- Addon server related entries
|
||||||
PARAM_PREFIX GroupUserConfigParam m_addon_group
|
PARAM_PREFIX GroupUserConfigParam m_addon_group
|
||||||
|
42
src/main.cpp
42
src/main.cpp
@ -215,6 +215,7 @@
|
|||||||
#include "network/protocols/get_public_address.hpp"
|
#include "network/protocols/get_public_address.hpp"
|
||||||
#include "online/profile_manager.hpp"
|
#include "online/profile_manager.hpp"
|
||||||
#include "online/request_manager.hpp"
|
#include "online/request_manager.hpp"
|
||||||
|
#include "online/steam.hpp"
|
||||||
#include "race/grand_prix_manager.hpp"
|
#include "race/grand_prix_manager.hpp"
|
||||||
#include "race/highscore_manager.hpp"
|
#include "race/highscore_manager.hpp"
|
||||||
#include "race/history.hpp"
|
#include "race/history.hpp"
|
||||||
@ -1458,6 +1459,16 @@ void askForInternetPermission()
|
|||||||
Online::RequestManager::IPERM_NOT_ASKED)
|
Online::RequestManager::IPERM_NOT_ASKED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// If a steam connection is available, we could skip the
|
||||||
|
// internet permission question (depending on settings).
|
||||||
|
if (Steam::get()->isSteamAvailable() &&
|
||||||
|
!stk_config->m_steam_ask_for_internet)
|
||||||
|
{
|
||||||
|
UserConfigParams::m_internet_status =
|
||||||
|
Online::RequestManager::IPERM_ALLOWED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
class ConfirmServer :
|
class ConfirmServer :
|
||||||
public MessageDialog::IConfirmDialogListener
|
public MessageDialog::IConfirmDialogListener
|
||||||
{
|
{
|
||||||
@ -1515,6 +1526,8 @@ int main(int argc, char *argv[] )
|
|||||||
{
|
{
|
||||||
CommandLine::init(argc, argv);
|
CommandLine::init(argc, argv);
|
||||||
|
|
||||||
|
Steam::create();
|
||||||
|
|
||||||
CrashReporting::installHandlers();
|
CrashReporting::installHandlers();
|
||||||
|
|
||||||
srand(( unsigned ) time( 0 ));
|
srand(( unsigned ) time( 0 ));
|
||||||
@ -1688,10 +1701,29 @@ int main(int argc, char *argv[] )
|
|||||||
// so we immediately start the main menu (unless it was requested
|
// so we immediately start the main menu (unless it was requested
|
||||||
// to always show the login screen). Otherwise show the login
|
// to always show the login screen). Otherwise show the login
|
||||||
// screen first.
|
// screen first.
|
||||||
if(PlayerManager::getCurrentPlayer() && !
|
if(PlayerManager::getCurrentPlayer() &&
|
||||||
UserConfigParams::m_always_show_login_screen)
|
!UserConfigParams::m_always_show_login_screen)
|
||||||
{
|
{
|
||||||
MainMenuScreen::getInstance()->push();
|
MainMenuScreen::getInstance()->push();
|
||||||
|
// If this is the first time that steam starts, and at startup
|
||||||
|
// we could not detect a 'matching' stk account to the steam
|
||||||
|
// account, bring up the user screen (on top of the main menu),
|
||||||
|
// so that the user can manually connect an stk account with
|
||||||
|
// a steam account.
|
||||||
|
if (UserConfigParams::m_steam_first_start &&
|
||||||
|
!PlayerManager::getCurrentPlayer()->isSteamUser())
|
||||||
|
{
|
||||||
|
UserScreen::getInstance()->push();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Steam::get()->isSteamAvailable())
|
||||||
|
{
|
||||||
|
PlayerProfile *steam_player = PlayerManager::get()
|
||||||
|
->addNewPlayer(Steam::get()->getUserNameWchar());
|
||||||
|
PlayerManager::get()->setCurrentPlayer(steam_player);
|
||||||
|
MainMenuScreen::getInstance()->push();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1704,7 +1736,8 @@ int main(int argc, char *argv[] )
|
|||||||
RegisterScreen::getInstance()->push();
|
RegisterScreen::getInstance()->push();
|
||||||
RegisterScreen::getInstance()->setParent(UserScreen::getInstance());
|
RegisterScreen::getInstance()->setParent(UserScreen::getInstance());
|
||||||
}
|
}
|
||||||
}
|
} // !steam->isAvailable
|
||||||
|
} // no player available
|
||||||
#ifdef ENABLE_WIIUSE
|
#ifdef ENABLE_WIIUSE
|
||||||
// Show a dialog to allow connection of wiimotes. */
|
// Show a dialog to allow connection of wiimotes. */
|
||||||
if(WiimoteManager::isEnabled())
|
if(WiimoteManager::isEnabled())
|
||||||
@ -1778,7 +1811,7 @@ int main(int argc, char *argv[] )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Program closing...*/
|
/* Program closing...*/
|
||||||
|
UserConfigParams::m_steam_first_start = false;
|
||||||
#ifdef ENABLE_WIIUSE
|
#ifdef ENABLE_WIIUSE
|
||||||
if(wiimote_manager)
|
if(wiimote_manager)
|
||||||
delete wiimote_manager;
|
delete wiimote_manager;
|
||||||
@ -1792,6 +1825,7 @@ int main(int argc, char *argv[] )
|
|||||||
if(NetworkConfig::get()->isNetworking() && STKHost::existHost())
|
if(NetworkConfig::get()->isNetworking() && STKHost::existHost())
|
||||||
STKHost::get()->abort();
|
STKHost::get()->abort();
|
||||||
|
|
||||||
|
Steam::destroy();
|
||||||
cleanSuperTuxKart();
|
cleanSuperTuxKart();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
389
src/online/steam.cpp
Normal file
389
src/online/steam.cpp
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2017 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include "online/steam.hpp"
|
||||||
|
|
||||||
|
#include "utils/log.hpp"
|
||||||
|
#include "utils/string_utils.hpp"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <windows.h>
|
||||||
|
#else
|
||||||
|
# include <iostream>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Steam * Steam::m_steam = NULL;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
Steam::Steam()
|
||||||
|
{
|
||||||
|
m_steam_available = false;
|
||||||
|
|
||||||
|
// Create the child process SSM to mamage steam:
|
||||||
|
if (!createChildProcess())
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Could not start ssm.exe");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("Steam", "Starting steam manager");
|
||||||
|
|
||||||
|
std::string s = sendCommand("init");
|
||||||
|
if (s != "1")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Could not initialise Steam API.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = sendCommand("name");
|
||||||
|
m_user_name = decodeString(s);
|
||||||
|
if (m_user_name == "")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Can not get Steam user name.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_user_name_wchar = StringUtils::utf8ToWide(m_user_name);
|
||||||
|
|
||||||
|
s = sendCommand("id");
|
||||||
|
m_steam_id = decodeString(s);
|
||||||
|
if (m_steam_id== "")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Can not get Steam id.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_steam_available = true;
|
||||||
|
} // Steam
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Terminates the child processes and shuts down the Steam API.
|
||||||
|
*/
|
||||||
|
Steam::~Steam()
|
||||||
|
{
|
||||||
|
std::string s = sendCommand("quit");
|
||||||
|
if (s != "quit")
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Could not shutdown Steam process properly");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LINUX
|
||||||
|
close(m_child_stdin_write);
|
||||||
|
close(m_child_stdout_read);
|
||||||
|
#endif
|
||||||
|
Log::info("Steam", "Shutting down steam manager");
|
||||||
|
|
||||||
|
} // ~Steam
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Starts ssm.exe (on windows) or ssm (other platforms) as a child process
|
||||||
|
* and sets up communication via pipes.
|
||||||
|
* \return True if the child process creation was successful.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
|
bool Steam::createChildProcess()
|
||||||
|
{
|
||||||
|
// Based on: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
|
||||||
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
|
|
||||||
|
// Set the bInheritHandle flag so pipe handles are inherited.
|
||||||
|
sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
sec_attr.bInheritHandle = TRUE;
|
||||||
|
sec_attr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
|
// Create a pipe for the child process's STDOUT.
|
||||||
|
|
||||||
|
if (!CreatePipe(&m_child_stdout_read, &m_child_stdout_write, &sec_attr, 0))
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Error creating StdoutRd CreatePipe");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
||||||
|
if (!SetHandleInformation(m_child_stdout_read, HANDLE_FLAG_INHERIT, 0))
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Stdout SetHandleInformation");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a pipe for the child process's STDIN.
|
||||||
|
if (!CreatePipe(&m_child_stdin_read, &m_child_stdin_write, &sec_attr, 0))
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Stdin CreatePipe");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the write handle to the pipe for STDIN is not inherited.
|
||||||
|
if (!SetHandleInformation(m_child_stdin_write, HANDLE_FLAG_INHERIT, 0))
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Stdin SetHandleInformation");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCHAR command_line[] = TEXT("ssm.exe");
|
||||||
|
PROCESS_INFORMATION piProcInfo;
|
||||||
|
STARTUPINFO siStartInfo;
|
||||||
|
|
||||||
|
// Set up members of the PROCESS_INFORMATION structure.
|
||||||
|
|
||||||
|
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
|
||||||
|
|
||||||
|
// Set up members of the STARTUPINFO structure.
|
||||||
|
// This structure specifies the STDIN and STDOUT handles for redirection.
|
||||||
|
|
||||||
|
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
|
||||||
|
siStartInfo.cb = sizeof(STARTUPINFO);
|
||||||
|
siStartInfo.hStdError = m_child_stdout_write;
|
||||||
|
siStartInfo.hStdOutput = m_child_stdout_write;
|
||||||
|
siStartInfo.hStdInput = m_child_stdin_read;
|
||||||
|
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
|
||||||
|
// Create the child process.
|
||||||
|
|
||||||
|
bool success = CreateProcess(NULL,
|
||||||
|
command_line, // command line
|
||||||
|
NULL, // process security attributes
|
||||||
|
NULL, // primary thread security attributes
|
||||||
|
TRUE, // handles are inherited
|
||||||
|
0, // creation flags
|
||||||
|
NULL, // use parent's environment
|
||||||
|
NULL, // use parent's current directory
|
||||||
|
&siStartInfo, // STARTUPINFO pointer
|
||||||
|
&piProcInfo) != 0; // receives PROCESS_INFORMATION
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close handles to the child process and its primary thread.
|
||||||
|
// Some applications might keep these handles to monitor the status
|
||||||
|
// of the child process, for example.
|
||||||
|
|
||||||
|
CloseHandle(piProcInfo.hProcess);
|
||||||
|
CloseHandle(piProcInfo.hThread);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // createChildProcess - windows version
|
||||||
|
|
||||||
|
#else // linux and osx
|
||||||
|
|
||||||
|
bool Steam::createChildProcess()
|
||||||
|
{
|
||||||
|
const int PIPE_READ=0;
|
||||||
|
const int PIPE_WRITE=1;
|
||||||
|
int stdin_pipe[2];
|
||||||
|
int stdout_pipe[2];
|
||||||
|
int child;
|
||||||
|
|
||||||
|
if (pipe(stdin_pipe) < 0)
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Can't allocate pipe for input redirection.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (pipe(stdout_pipe) < 0)
|
||||||
|
{
|
||||||
|
close(stdin_pipe[PIPE_READ]);
|
||||||
|
close(stdin_pipe[PIPE_WRITE]);
|
||||||
|
Log::error("Steam", "allocating pipe for child output redirect");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
if (child == 0)
|
||||||
|
{
|
||||||
|
// Child process:
|
||||||
|
Log::info("Steam", "Child process started.");
|
||||||
|
|
||||||
|
// redirect stdin
|
||||||
|
if (dup2(stdin_pipe[PIPE_READ], STDIN_FILENO) == -1)
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Redirecting stdin");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// redirect stdout
|
||||||
|
if (dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO) == -1)
|
||||||
|
{
|
||||||
|
Log::error("Steam", "Redirecting stdout");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all these are for use by parent only
|
||||||
|
close(stdin_pipe[PIPE_READ]);
|
||||||
|
close(stdin_pipe[PIPE_WRITE]);
|
||||||
|
close(stdout_pipe[PIPE_READ]);
|
||||||
|
close(stdout_pipe[PIPE_WRITE]);
|
||||||
|
|
||||||
|
// run child process image
|
||||||
|
execl("./ssm", "", NULL);
|
||||||
|
Log::error("Steam", "Error in execl: errnp %d", errno);
|
||||||
|
|
||||||
|
// if we get here at all, an error occurred, but we are in the child
|
||||||
|
// process, so just exit
|
||||||
|
perror("Steam: execl error");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
else if (child > 0)
|
||||||
|
{
|
||||||
|
// parent continues here
|
||||||
|
// close unused file descriptors, these are for child only
|
||||||
|
close(stdin_pipe[PIPE_READ]);
|
||||||
|
close(stdout_pipe[PIPE_WRITE]);
|
||||||
|
m_child_stdin_write = stdin_pipe[PIPE_WRITE];
|
||||||
|
m_child_stdout_read = stdout_pipe[PIPE_READ];
|
||||||
|
}
|
||||||
|
else // child < 0
|
||||||
|
{
|
||||||
|
// failed to create child
|
||||||
|
close(stdin_pipe[PIPE_READ]);
|
||||||
|
close(stdin_pipe[PIPE_WRITE]);
|
||||||
|
close(stdout_pipe[PIPE_READ]);
|
||||||
|
close(stdout_pipe[PIPE_WRITE]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // createChildProcess
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Reads a command from the input pipe.
|
||||||
|
*/
|
||||||
|
std::string Steam::getLine()
|
||||||
|
{
|
||||||
|
#define BUFSIZE 1024
|
||||||
|
char buffer[BUFSIZE];
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD bytes_read;
|
||||||
|
// Read from pipe that is the standard output for child process.
|
||||||
|
bool success = ReadFile(m_child_stdout_read, buffer, BUFSIZE-1,
|
||||||
|
&bytes_read, NULL)!=0;
|
||||||
|
if (success && bytes_read < BUFSIZE)
|
||||||
|
{
|
||||||
|
buffer[bytes_read] = 0;
|
||||||
|
std::string s = buffer;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
//std::string s;
|
||||||
|
//std::getline(std::cin, s);
|
||||||
|
//return s;
|
||||||
|
|
||||||
|
int bytes_read = read(m_child_stdout_read, buffer, BUFSIZE-1);
|
||||||
|
if(bytes_read>0)
|
||||||
|
{
|
||||||
|
buffer[bytes_read] = 0;
|
||||||
|
std::string s = buffer;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return std::string("");
|
||||||
|
} // getLine
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Sends a command to the SSM via a pipe, and reads the answer.
|
||||||
|
* \return Answer from SSM.
|
||||||
|
*/
|
||||||
|
std::string Steam::sendCommand(const std::string &command)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
// Write to the pipe that is the standard input for a child process.
|
||||||
|
// Data is written to the pipe's buffers, so it is not necessary to wait
|
||||||
|
// until the child process is running before writing data.
|
||||||
|
DWORD bytes_written;
|
||||||
|
bool success = WriteFile(m_child_stdin_write, command.c_str(),
|
||||||
|
command.size()+1, &bytes_written, NULL ) != 0;
|
||||||
|
#else
|
||||||
|
write(m_child_stdin_write, (command+"\n").c_str(), command.size()+1);
|
||||||
|
#endif
|
||||||
|
return getLine();
|
||||||
|
|
||||||
|
return std::string("");
|
||||||
|
} // sendCommand
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** All answer strings from 'SSM' are in the form: "length string", i.e. the
|
||||||
|
* length of the string, followed by a space and then the actual strings.
|
||||||
|
* This allows for checking on some potential problems (e.g. if a pipe should
|
||||||
|
* only send part of the answer string - todo: handle this problem instead of
|
||||||
|
* ignoring it.
|
||||||
|
*/
|
||||||
|
std::string Steam::decodeString(const std::string &s)
|
||||||
|
{
|
||||||
|
std::vector<std::string> l = StringUtils::split(s, ' ');
|
||||||
|
if (l.size() != 2) return "INVALID ANSWER - wrong number of fields";
|
||||||
|
|
||||||
|
int n;
|
||||||
|
StringUtils::fromString(l[0], n);
|
||||||
|
if (n != (int)l[1].size()) return "INVALID ANSWER - incorrect length";
|
||||||
|
|
||||||
|
return l[1];
|
||||||
|
|
||||||
|
} // decodeString
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Returns the steam user name. SSM returns 'N name" where N is
|
||||||
|
* the length of the name.
|
||||||
|
*/
|
||||||
|
const std::string& Steam::getUserName()
|
||||||
|
{
|
||||||
|
assert(m_steam_available);
|
||||||
|
return m_user_name;
|
||||||
|
} // getUserName
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Returns a unique id (string) from steam. SSM returns 'N ID" where N is
|
||||||
|
* the length of the ID.
|
||||||
|
*/
|
||||||
|
const std::string& Steam::getSteamID()
|
||||||
|
{
|
||||||
|
assert(m_steam_available);
|
||||||
|
return m_steam_id;
|
||||||
|
} // getSteamID
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Returns a std::vector with the names of all friends. SSM returns a first
|
||||||
|
* line with the number of friends, then one friend in a line.
|
||||||
|
*/
|
||||||
|
std::vector<std::string> Steam::getFriends()
|
||||||
|
{
|
||||||
|
std::string s = sendCommand("friends");
|
||||||
|
int num_friends;
|
||||||
|
StringUtils::fromString(s, num_friends);
|
||||||
|
std::vector<std::string> result;
|
||||||
|
for (int i = 0; i < num_friends; i++)
|
||||||
|
{
|
||||||
|
std::string f = getLine();
|
||||||
|
result.push_back(decodeString(f));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Instructs the SSM to save the avatar of the user with the specified
|
||||||
|
* filename. Note that the avatar is always saved in png format (independent
|
||||||
|
* on what is specified as filename).
|
||||||
|
*/
|
||||||
|
int Steam::saveAvatarAs(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::string s = sendCommand("avatar");
|
||||||
|
if(s=="filename")
|
||||||
|
s=sendCommand(filename);
|
||||||
|
return s == "done";
|
||||||
|
|
||||||
|
} // saveAvatarAs
|
123
src/online/steam.hpp
Normal file
123
src/online/steam.hpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2017 Joerg Henrichs
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef HEADER_STEAM_HPP
|
||||||
|
#define HEADER_STEAM_HPP
|
||||||
|
|
||||||
|
#include "irrString.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/** This class provides a simple interface to the SteamWorks API. Due to
|
||||||
|
* our current license, the SteamWorks lib can not be linked with STK.
|
||||||
|
* So this wrapper class actually starts a seprate process (ssm, see
|
||||||
|
* https://github.com/hiker/steam-synchron-manager) and communicats
|
||||||
|
* with the SSM using pipes.
|
||||||
|
*/
|
||||||
|
class Steam
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/** Singleton pointer. */
|
||||||
|
static Steam *m_steam;
|
||||||
|
|
||||||
|
/** True if a connection to steam was made successfully. */
|
||||||
|
bool m_steam_available;
|
||||||
|
|
||||||
|
/** Steam user name. Only defined if m_steam_available. */
|
||||||
|
std::string m_user_name;
|
||||||
|
|
||||||
|
/** User name as irr::stringw (wchar), which is used in STK. */
|
||||||
|
irr::core::stringw m_user_name_wchar;
|
||||||
|
|
||||||
|
/** Unique steam id. */
|
||||||
|
std::string m_steam_id;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// Various handles for the window pipes
|
||||||
|
HANDLE m_child_stdin_read;
|
||||||
|
HANDLE m_child_stdin_write;
|
||||||
|
HANDLE m_child_stdout_read;
|
||||||
|
HANDLE m_child_stdout_write;
|
||||||
|
|
||||||
|
#else
|
||||||
|
int m_child_stdin_read;
|
||||||
|
int m_child_stdin_write;
|
||||||
|
int m_child_stdout_read;
|
||||||
|
int m_child_stdout_write;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
bool createChildProcess();
|
||||||
|
|
||||||
|
std::string decodeString(const std::string &s);
|
||||||
|
std::string sendCommand(const std::string &command);
|
||||||
|
std::string getLine();
|
||||||
|
|
||||||
|
Steam();
|
||||||
|
~Steam();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Creates a singleton. */
|
||||||
|
static void create()
|
||||||
|
{
|
||||||
|
assert(!m_steam);
|
||||||
|
m_steam = new Steam();
|
||||||
|
} // create;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the singleton pf the Steam class. */
|
||||||
|
static Steam *get()
|
||||||
|
{
|
||||||
|
assert(m_steam);
|
||||||
|
return m_steam;
|
||||||
|
} // get
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Destroys the singleton of the Steam class. */
|
||||||
|
static void destroy()
|
||||||
|
{
|
||||||
|
assert(m_steam);
|
||||||
|
delete m_steam;
|
||||||
|
m_steam = NULL;
|
||||||
|
} // destroy
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const std::string& getUserName();
|
||||||
|
const std::string& getSteamID();
|
||||||
|
int saveAvatarAs(const std::string &filename);
|
||||||
|
std::vector<std::string> getFriends();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns the user name as wide string. */
|
||||||
|
const irr::core::stringw& getUserNameWchar()
|
||||||
|
{
|
||||||
|
assert(m_steam_available);
|
||||||
|
return m_user_name_wchar;
|
||||||
|
} // getUserNameWchar
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns true if the connection to the Steam API was successful, i.e.
|
||||||
|
* connection to steam worked, and SteamWorks API could be initialised. */
|
||||||
|
bool isSteamAvailable() const { return m_steam_available; }
|
||||||
|
}; // class Steam
|
||||||
|
|
||||||
|
#endif // HEADER_STEAM_HPP
|
@ -24,6 +24,7 @@
|
|||||||
#include "guiengine/widgets/label_widget.hpp"
|
#include "guiengine/widgets/label_widget.hpp"
|
||||||
#include "guiengine/widgets/ribbon_widget.hpp"
|
#include "guiengine/widgets/ribbon_widget.hpp"
|
||||||
#include "guiengine/widgets/text_box_widget.hpp"
|
#include "guiengine/widgets/text_box_widget.hpp"
|
||||||
|
#include "online/steam.hpp"
|
||||||
#include "online/xml_request.hpp"
|
#include "online/xml_request.hpp"
|
||||||
#include "states_screens/dialogs/registration_dialog.hpp"
|
#include "states_screens/dialogs/registration_dialog.hpp"
|
||||||
#include "states_screens/dialogs/message_dialog.hpp"
|
#include "states_screens/dialogs/message_dialog.hpp"
|
||||||
@ -88,7 +89,9 @@ void RegisterScreen::init()
|
|||||||
}
|
}
|
||||||
else if (PlayerManager::get()->getNumPlayers() == 0)
|
else if (PlayerManager::get()->getNumPlayers() == 0)
|
||||||
{
|
{
|
||||||
if (getenv("USERNAME") != NULL) // for windows
|
if (Steam::get()->isSteamAvailable())
|
||||||
|
username = StringUtils::utf8ToWide( Steam::get()->getUserName());
|
||||||
|
else if (getenv("USERNAME") != NULL) // for windows
|
||||||
username = getenv("USERNAME");
|
username = getenv("USERNAME");
|
||||||
else if (getenv("USER") != NULL) // Linux, Macs
|
else if (getenv("USER") != NULL) // Linux, Macs
|
||||||
username = getenv("USER");
|
username = getenv("USER");
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "guiengine/widgets/label_widget.hpp"
|
#include "guiengine/widgets/label_widget.hpp"
|
||||||
#include "guiengine/widgets/list_widget.hpp"
|
#include "guiengine/widgets/list_widget.hpp"
|
||||||
#include "guiengine/widgets/text_box_widget.hpp"
|
#include "guiengine/widgets/text_box_widget.hpp"
|
||||||
|
#include "online/steam.hpp"
|
||||||
#include "states_screens/dialogs/message_dialog.hpp"
|
#include "states_screens/dialogs/message_dialog.hpp"
|
||||||
#include "states_screens/dialogs/recovery_dialog.hpp"
|
#include "states_screens/dialogs/recovery_dialog.hpp"
|
||||||
#include "states_screens/main_menu_screen.hpp"
|
#include "states_screens/main_menu_screen.hpp"
|
||||||
@ -55,6 +56,10 @@ BaseUserScreen::BaseUserScreen(const std::string &name) : Screen(name.c_str())
|
|||||||
|
|
||||||
void BaseUserScreen::loadedFromFile()
|
void BaseUserScreen::loadedFromFile()
|
||||||
{
|
{
|
||||||
|
m_steam_cb = getWidget<CheckBoxWidget>("steam");
|
||||||
|
assert(m_steam_cb);
|
||||||
|
m_steam_label = getWidget<LabelWidget>("label-steam");
|
||||||
|
assert(m_steam_label);
|
||||||
m_online_cb = getWidget<CheckBoxWidget>("online");
|
m_online_cb = getWidget<CheckBoxWidget>("online");
|
||||||
assert(m_online_cb);
|
assert(m_online_cb);
|
||||||
m_username_tb = getWidget<TextBoxWidget >("username");
|
m_username_tb = getWidget<TextBoxWidget >("username");
|
||||||
@ -218,6 +223,27 @@ void BaseUserScreen::selectUser(int index)
|
|||||||
m_players->setSelection(StringUtils::toString(index), PLAYER_ID_GAME_MASTER,
|
m_players->setSelection(StringUtils::toString(index), PLAYER_ID_GAME_MASTER,
|
||||||
focus_it);
|
focus_it);
|
||||||
|
|
||||||
|
m_steam_cb->setVisible (Steam::get()->isSteamAvailable());
|
||||||
|
m_steam_label->setVisible(Steam::get()->isSteamAvailable());
|
||||||
|
if (Steam::get()->isSteamAvailable())
|
||||||
|
{
|
||||||
|
m_steam_cb->setState(profile->isSteamUser());
|
||||||
|
if (profile->isSteamUser())
|
||||||
|
{
|
||||||
|
//I18N: Checkbox text shown when this player is a steam user
|
||||||
|
// with the name displayed in ().
|
||||||
|
core::stringw label = _("Is Steam user (%s)",
|
||||||
|
profile->getSteamName() );
|
||||||
|
m_steam_label->setText(label, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//I18N: Checbox text shown when the user is not a steam user
|
||||||
|
// but can select the check box in order to become one
|
||||||
|
m_steam_label->setText(_("Is Steam user"), true);
|
||||||
|
} // no steam user
|
||||||
|
} // If steam is available
|
||||||
|
|
||||||
if (!m_new_registered_data)
|
if (!m_new_registered_data)
|
||||||
m_username_tb->setText(profile->getLastOnlineName(true/*ignoreRTL*/));
|
m_username_tb->setText(profile->getLastOnlineName(true/*ignoreRTL*/));
|
||||||
|
|
||||||
@ -300,8 +326,7 @@ void BaseUserScreen::makeEntryFieldsVisible()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Called when the user selects anything on the screen.
|
/** Called when the user selects anything on the screen.
|
||||||
*/
|
*/
|
||||||
void BaseUserScreen::eventCallback(Widget* widget,
|
void BaseUserScreen::eventCallback(Widget* widget, const std::string& name,
|
||||||
const std::string& name,
|
|
||||||
const int player_id)
|
const int player_id)
|
||||||
{
|
{
|
||||||
// Clean any error message still shown
|
// Clean any error message still shown
|
||||||
@ -389,11 +414,47 @@ void BaseUserScreen::eventCallback(Widget* widget,
|
|||||||
{
|
{
|
||||||
StateManager::get()->escapePressed();
|
StateManager::get()->escapePressed();
|
||||||
}
|
}
|
||||||
|
else if (name == "steam")
|
||||||
|
{
|
||||||
|
handleSteamAccount(player_id);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
} // eventCallback
|
} // eventCallback
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Called when an STK account is connected or disconnected to a steam
|
||||||
|
* account.
|
||||||
|
* \param player_id The index of the currently selected player.
|
||||||
|
*/
|
||||||
|
void BaseUserScreen::handleSteamAccount(int player_id)
|
||||||
|
{
|
||||||
|
// Shouldn't happen, this option is only shown when
|
||||||
|
// steam is available
|
||||||
|
if (!Steam::get()->isSteamAvailable()) return;
|
||||||
|
|
||||||
|
const std::string &s_index = getWidget<DynamicRibbonWidget>("players")
|
||||||
|
->getSelectionIDString(player_id);
|
||||||
|
|
||||||
|
if (s_index == "") return; // can happen if the list is empty
|
||||||
|
|
||||||
|
unsigned int id = 0;
|
||||||
|
StringUtils::fromString(s_index, id);
|
||||||
|
PlayerProfile *profile = PlayerManager::get()->getPlayer(id);
|
||||||
|
|
||||||
|
if (m_steam_cb->getState())
|
||||||
|
{
|
||||||
|
// We need to disconnect any other STK account which uses the
|
||||||
|
// same steam account
|
||||||
|
PlayerManager::get()->disconnectSteamAccount(Steam::get()->getSteamID());
|
||||||
|
profile->setToCurrentSteamUser();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
profile->clearSteamData();
|
||||||
|
|
||||||
|
selectUser(id);
|
||||||
|
} // handleSteamAccount
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Closes the BaseUserScreen, and makes sure that the right screen is displayed
|
/** Closes the BaseUserScreen, and makes sure that the right screen is displayed
|
||||||
* next.
|
* next.
|
||||||
|
@ -65,6 +65,12 @@ private:
|
|||||||
* display more meaningful sign-out message. */
|
* display more meaningful sign-out message. */
|
||||||
irr::core::stringw m_sign_in_name;
|
irr::core::stringw m_sign_in_name;
|
||||||
|
|
||||||
|
/** Online check box. */
|
||||||
|
GUIEngine::CheckBoxWidget *m_steam_cb;
|
||||||
|
|
||||||
|
/** Label field for steam details. */
|
||||||
|
GUIEngine::LabelWidget * m_steam_label;
|
||||||
|
|
||||||
/** Online check box. */
|
/** Online check box. */
|
||||||
GUIEngine::CheckBoxWidget *m_online_cb;
|
GUIEngine::CheckBoxWidget *m_online_cb;
|
||||||
|
|
||||||
@ -98,6 +104,7 @@ private:
|
|||||||
void closeScreen();
|
void closeScreen();
|
||||||
void deletePlayer();
|
void deletePlayer();
|
||||||
void doDeletePlayer();
|
void doDeletePlayer();
|
||||||
|
void handleSteamAccount(int player_id);
|
||||||
PlayerProfile* getSelectedPlayer();
|
PlayerProfile* getSelectedPlayer();
|
||||||
virtual void onUpdate(float dt) OVERRIDE;
|
virtual void onUpdate(float dt) OVERRIDE;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user