1 //  SuperTuxKart - a fun racing game with go-kart
2 //  Copyright (C) 2013-2015 Glenn De Jonghe
3 //
4 //  This program is free software; you can redistribute it and/or
5 //  modify it under the terms of the GNU General Public License
6 //  as published by the Free Software Foundation; either version 3
7 //  of the License, or (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 
18 #include "network/server.hpp"
19 #include "config/player_manager.hpp"
20 #include "io/xml_node.hpp"
21 #include "online/online_player_profile.hpp"
22 #include "online/online_profile.hpp"
23 #include "online/profile_manager.hpp"
24 #include "network/network_config.hpp"
25 #include "network/socket_address.hpp"
26 #include "states_screens/online/online_screen.hpp"
27 #include "tracks/track_manager.hpp"
28 #include "utils/constants.hpp"
29 #include "utils/string_utils.hpp"
30 
31 #include <algorithm>
32 
33 /** Constructor based on XML data received from the stk server.
34  *  \param xml The data for one server as received as part of the
35  *         get-all stk-server request.
36  */
Server(const XMLNode & server_info)37 Server::Server(const XMLNode& server_info) : m_supports_encrytion(true)
38 {
39     const XMLNode& xml = *server_info.getNode("server-info");
40     m_address.reset(new SocketAddress());
41 
42     m_reconnect_when_quit_lobby = false;
43     m_ipv6_connection = false;
44     m_name = "";
45     m_server_id = 0;
46     m_current_players = 0;
47     m_max_players = 0;
48     m_distance = 0.0f;
49     m_server_mode = 0;
50     xml.get("game_mode", &m_server_mode);
51     unsigned server_data = 0;
52     xml.get("difficulty", &server_data);
53     m_difficulty = (RaceManager::Difficulty)server_data;
54 
55     xml.get("name", &m_lower_case_name);
56     m_name = StringUtils::xmlDecode(m_lower_case_name);
57     m_lower_case_name = StringUtils::toLowerCase(
58         StringUtils::wideToUtf8(m_name));
59 
60     xml.get("id", &m_server_id);
61     xml.get("host_id", &m_server_owner);
62     xml.get("max_players", &m_max_players);
63     xml.get("current_players", &m_current_players);
64     xml.get("current_track", &m_current_track);
65     uint32_t ip;
66     xml.get("ip", &ip);
67     m_address->setIP(ip);
68     uint16_t port;
69     xml.get("port", &port);
70     m_address->setPort(port);
71     std::string ipv6_address;
72     xml.get("ipv6", &ipv6_address);
73     if (!ipv6_address.empty())
74         m_ipv6_address.reset(new SocketAddress(ipv6_address, port));
75     xml.get("private_port", &m_private_port);
76     xml.get("password", &m_password_protected);
77     xml.get("game_started", &m_game_started);
78     xml.get("distance", &m_distance);
79     xml.get("country_code", &m_country_code);
80     m_server_owner_name = L"-";
81     m_server_owner_lower_case_name = "-";
82 
83     const XMLNode* players = server_info.getNode("players");
84     assert(players);
85     for (unsigned int i = 0; i < players->getNumNodes(); i++)
86     {
87         const XMLNode* player_info = players->getNode(i);
88         assert(player_info->getName() == "player-info");
89         std::string username;
90         std::tuple<int, core::stringw, double, float> t;
91         // Default rank and scores if none
92         std::get<0>(t) = -1;
93         std::get<2>(t) = 2000.0;
94         player_info->get("rank", &std::get<0>(t));
95         player_info->get("username", &username);
96         std::get<1>(t) = StringUtils::utf8ToWide(username);
97         std::string country;
98         player_info->get("country-code", &country);
99         const core::stringw& flag = StringUtils::getCountryFlag(country);
100         if (!flag.empty())
101         {
102             std::get<1>(t) += L" ";
103             std::get<1>(t) += flag;
104         }
105         m_lower_case_player_names += StringUtils::toLowerCase(username);
106         player_info->get("scores", &std::get<2>(t));
107         float time_played = 0.0f;
108         player_info->get("time-played", &time_played);
109         std::get<3>(t) = time_played;
110         m_players.push_back(t);
111     }
112     // Sort by rank
113     std::sort(m_players.begin(), m_players.end(),
114         [](const std::tuple<int, core::stringw, double, float>& a,
115         const std::tuple<int, core::stringw, double, float>& b)->bool
116         {
117             return std::get<0>(a) < std::get<0>(b);
118         });
119 
120     // Show owner name as Official right now if official server hoster account
121     m_official = false;
122     xml.get("official", &m_official);
123     if (m_official)
124     {
125         m_server_owner_name = L"\u2606\u2605STK\u2605\u2606";
126         m_server_owner_lower_case_name = "stk";
127         return;
128     }
129 
130     // Display server owner name if they're your friend or localhost
131     Online::OnlineProfile* opp =
132         PlayerManager::getCurrentPlayer()->getProfile();
133     // Check localhost owner
134     if (opp && opp->getID() == m_server_owner)
135     {
136         m_server_owner_name = opp->getUserName();
137         m_server_owner_lower_case_name = StringUtils::toLowerCase
138             (StringUtils::wideToUtf8(m_server_owner_name));
139     }
140     else if (opp && opp->hasFetchedFriends())
141     {
142         // Check friend(s)
143         for (uint32_t user_id : opp->getFriends())
144         {
145             if (user_id == m_server_owner)
146             {
147                 Online::OnlineProfile* friend_profile =
148                     Online::ProfileManager::get()->getProfileByID(user_id);
149                 if (friend_profile)
150                 {
151                     m_server_owner_name = friend_profile->getUserName();
152                     m_server_owner_lower_case_name = StringUtils::toLowerCase
153                         (StringUtils::wideToUtf8(m_server_owner_name));
154                 }
155             }
156         }
157     }
158 
159 } // Server(const XML&)
160 
161 // ----------------------------------------------------------------------------
162 /** Manual server creation, based on data received from a LAN server discovery
163  *  (see ServersManager::getLANRefresh) or local graphics server creation
164  *  where the server info is known already.
165  *  \param server_id ID of server.
166  *  \param name Name of the server.
167  *  \param max_players Maximum number of players allowed on this server.
168  *  \param current_players The currently connected number of players.
169  *  \param difficulty The difficulty of the server.
170  *  \param server_mode The game modes of the server (including minor and major).
171  *  \param address IP and port of the server.
172  *  \param password_protected True if can only be joined with a password.
173  *  \param game_started True if a game has already begun in the server.
174  *  \param current_track If server is in game, store the track ident
175  */
Server(unsigned server_id,const core::stringw & name,int max_players,int current_players,unsigned difficulty,unsigned server_mode,const SocketAddress & address,bool password_protected,bool game_started,const std::string & current_track)176 Server::Server(unsigned server_id, const core::stringw &name, int max_players,
177                int current_players, unsigned difficulty, unsigned server_mode,
178                const SocketAddress &address, bool password_protected,
179                bool game_started, const std::string& current_track)
180       : m_supports_encrytion(false)
181 {
182     m_reconnect_when_quit_lobby = false;
183     m_ipv6_connection = false;
184     m_name               = name;
185     m_lower_case_name    = StringUtils::toLowerCase(StringUtils::wideToUtf8(name));
186     m_server_id          = server_id;
187     m_server_owner       = 0;
188     m_current_players    = current_players;
189     m_max_players        = max_players;
190     m_address.reset(new SocketAddress(address));
191 
192     // In case of LAN server, public and private port are the same.
193     m_private_port       = m_address->getPort();
194     m_difficulty         = (RaceManager::Difficulty)difficulty;
195     m_server_mode        = server_mode;
196     m_password_protected = password_protected;
197     m_distance = 0.0f;
198     m_official = false;
199     m_game_started = game_started;
200     m_current_track = current_track;
201 }   // server(server_id, ...)
202 
203 // ----------------------------------------------------------------------------
~Server()204 Server::~Server()
205 {
206 }   // ~Server
207 
208 // ----------------------------------------------------------------------------
getCurrentTrack() const209 Track* Server::getCurrentTrack() const
210 {
211     if (!m_current_track.empty())
212         return track_manager->getTrack(m_current_track);
213     return NULL;
214 }   // getCurrentTrack
215 
216 // ----------------------------------------------------------------------------
searchByName(const std::string & lower_case_word)217 bool Server::searchByName(const std::string& lower_case_word)
218 {
219     auto list = StringUtils::split(lower_case_word, ' ', false);
220     bool server_name_found = true;
221     for (auto& word : list)
222     {
223         const std::string& for_search = m_lower_case_name +
224             m_lower_case_player_names;
225         server_name_found = server_name_found &&
226             for_search.find(word) != std::string::npos;
227     }
228     return server_name_found;
229 }   // searchByName
230 
231 // ----------------------------------------------------------------------------
setIPV6Address(const SocketAddress & addr)232 void Server::setIPV6Address(const SocketAddress& addr)
233 {
234     m_ipv6_address.reset(new SocketAddress(addr));
235 }   // setIPV6Address
236 
237 // ----------------------------------------------------------------------------
setAddress(const SocketAddress & addr)238 void Server::setAddress(const SocketAddress& addr)
239 {
240     m_address.reset(new SocketAddress(addr));
241 }   // setAddress
242 
243 // ----------------------------------------------------------------------------
saveServer() const244 void UserDefinedServer::saveServer() const
245 {
246     OnlineScreen::getInstance()->setEnteredServerName(m_name);
247 }   // saveServer
248