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 "states_screens/dialogs/server_info_dialog.hpp"
19 
20 #include "guiengine/engine.hpp"
21 #include "guiengine/widgets/icon_button_widget.hpp"
22 #include "guiengine/widgets/label_widget.hpp"
23 #include "guiengine/widgets/list_widget.hpp"
24 #include "guiengine/widgets/ribbon_widget.hpp"
25 #include "guiengine/widgets/text_box_widget.hpp"
26 #include "network/server.hpp"
27 #include "network/server_config.hpp"
28 #include "network/stk_host.hpp"
29 #include "states_screens/online/networking_lobby.hpp"
30 #include "states_screens/state_manager.hpp"
31 #include "tracks/track.hpp"
32 #include "utils/string_utils.hpp"
33 #include "utils/translation.hpp"
34 
35 #include <IGUIEnvironment.h>
36 
37 using namespace GUIEngine;
38 using namespace irr;
39 using namespace irr::gui;
40 using namespace Online;
41 
42 // -----------------------------------------------------------------------------
43 /** Dialog constructor.
44  *  \param server_id ID of the server of which to display the info.
45  *  \param host_id ID of the host.
46  *  \param from_server_creation: true if the dialog shows the data of this
47  *         server (i.e. while it is being created).
48  */
ServerInfoDialog(std::shared_ptr<Server> server)49 ServerInfoDialog::ServerInfoDialog(std::shared_ptr<Server> server)
50                 : ModalDialog(0.85f,0.85f), m_server(server), m_password(NULL)
51 {
52     Log::info("ServerInfoDialog", "Server id is %d, owner is %d",
53        server->getServerId(), server->getServerOwner());
54     m_self_destroy = false;
55     m_join_server = false;
56 
57     loadFromFile("online/server_info_dialog.stkgui");
58     getWidget<LabelWidget>("title")->setText(server->getName(), true);
59 
60     m_options_widget = getWidget<RibbonWidget>("options");
61     assert(m_options_widget != NULL);
62     m_join_widget = getWidget<IconButtonWidget>("join");
63     assert(m_join_widget != NULL);
64     m_cancel_widget = getWidget<IconButtonWidget>("cancel");
65     assert(m_cancel_widget != NULL);
66 
67     if (m_server->isPasswordProtected())
68     {
69         m_password = getWidget<TextBoxWidget>("password");
70         m_password->setPasswordBox(true, L'*');
71         assert(m_password != NULL);
72         m_password->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
73     }
74     else
75     {
76         Widget* password_box = getWidget("password-box");
77         password_box->setCollapsed(true); // FIXME Doesn't reuse free space for other widgets
78         m_options_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
79     }
80 
81     core::stringw difficulty = RaceManager::get()->getDifficultyName(
82         server->getDifficulty());
83     //I18N: In server info dialog
84     getWidget<LabelWidget>("server-info-1")->setText(_("Difficulty: %s", difficulty), false);
85 
86     core::stringw mode = ServerConfig::getModeName(server->getServerMode());
87     //I18N: In server info dialog
88     getWidget<LabelWidget>("server-info-2")->setText(_("Game mode: %s", mode), false);
89 
90 #ifndef SERVER_ONLY
91     if (!server->getCountryCode().empty())
92     {
93         core::stringw country_name =
94             translations->getLocalizedCountryName(server->getCountryCode());
95         //I18N: In the server info dialog, show the server location with
96         //country name (based on IP geolocation)
97         getWidget<LabelWidget>("server-info-3")->setText(_("Server location: %s", country_name), false);
98     }
99 #endif
100 
101     Track* t = server->getCurrentTrack();
102     if (t)
103     {
104         core::stringw track_name = t->getName();
105         //I18N: In server info dialog, showing the current track playing in server
106         getWidget<LabelWidget>("server-info-4")->setText(_("Current track: %s", track_name), false);
107     }
108 
109     auto& players = m_server->getPlayers();
110     if (!players.empty())
111     {
112         // I18N: Show above the player list in server info dialog to
113         // indicate the row meanings
114         ListWidget* player_list = getWidget<ListWidget>("player-list");
115         std::vector<ListWidget::ListCell> row;
116         row.push_back(ListWidget::ListCell(_("Rank"), -1, 1, true));
117         // I18N: Show above the player list in server info dialog, tell
118         // the user name on server
119         row.push_back(ListWidget::ListCell(_("Player"), -1, 2, true));
120         // I18N: Show above the player list in server info dialog, tell
121         // the scores of user calculated by player rankings
122         row.push_back(ListWidget::ListCell(_("Scores"), -1, 1, true));
123         // I18N: Show above the player list in server info dialog, tell
124         // the user time played on server
125         row.push_back(ListWidget::ListCell(_("Time played"),
126             -1, 1, true));
127         player_list->addItem("player", row);
128         for (auto& r : players)
129         {
130             row.clear();
131             row.push_back(ListWidget::ListCell(
132                 std::get<0>(r) == -1 ? L"-" :
133                 StringUtils::toWString(std::get<0>(r)), -1, 1, true));
134             row.push_back(ListWidget::ListCell(std::get<1>(r), -1,
135                 2, true));
136             row.push_back(ListWidget::ListCell(
137                 std::get<0>(r) == -1 ? L"-" :
138                 StringUtils::toWString(std::get<2>(r)), -1, 1, true));
139             row.push_back(ListWidget::ListCell(
140                 StringUtils::toWString(std::get<3>(r)), -1, 1, true));
141             player_list->addItem("player", row);
142         }
143     }
144     else
145     {
146         getWidget("player-list")->setVisible(false);
147     }
148 }   // ServerInfoDialog
149 
150 // -----------------------------------------------------------------------------
~ServerInfoDialog()151 ServerInfoDialog::~ServerInfoDialog()
152 {
153 }   // ~ServerInfoDialog
154 
155 // -----------------------------------------------------------------------------
requestJoin()156 void ServerInfoDialog::requestJoin()
157 {
158     if (m_server->isPasswordProtected())
159     {
160         assert(m_password != NULL);
161         if (m_password->getText().empty())
162             return;
163         ServerConfig::m_private_server_password =
164             StringUtils::wideToUtf8(m_password->getText());
165     }
166     else
167     {
168         ServerConfig::m_private_server_password = "";
169     }
170     STKHost::create();
171     NetworkingLobby::getInstance()->setJoinedServer(m_server);
172     ModalDialog::dismiss();
173     NetworkingLobby::getInstance()->push();
174 }   // requestJoin
175 
176 // -----------------------------------------------------------------------------
177 GUIEngine::EventPropagation
processEvent(const std::string & eventSource)178                  ServerInfoDialog::processEvent(const std::string& eventSource)
179 {
180     if (eventSource == m_options_widget->m_properties[PROP_ID])
181     {
182         const std::string& selection =
183                  m_options_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
184         if (selection == m_cancel_widget->m_properties[PROP_ID])
185         {
186             m_self_destroy = true;
187             return GUIEngine::EVENT_BLOCK;
188         }
189         else if(selection == m_join_widget->m_properties[PROP_ID])
190         {
191             m_join_server = true;
192             return GUIEngine::EVENT_BLOCK;
193         }
194     }
195     return GUIEngine::EVENT_LET;
196 }   // processEvent
197 
198 // -----------------------------------------------------------------------------
199 /** When the player pressed enter, select 'join' as default.
200  */
onEnterPressedInternal()201 void ServerInfoDialog::onEnterPressedInternal()
202 {
203     // If enter was pressed while none of the buttons was focused interpret
204     // as join event
205     const int playerID = PLAYER_ID_GAME_MASTER;
206     if (GUIEngine::isFocusedForPlayer(m_options_widget, playerID))
207         return;
208     m_join_server = true;
209 }   // onEnterPressedInternal
210 
211 // -----------------------------------------------------------------------------
212 
onEscapePressed()213 bool ServerInfoDialog::onEscapePressed()
214 {
215     if (m_cancel_widget->isActivated())
216         m_self_destroy = true;
217     return false;
218 }   // onEscapePressed
219 
220 // -----------------------------------------------------------------------------
onUpdate(float dt)221 void ServerInfoDialog::onUpdate(float dt)
222 {
223     if (m_password && m_password->getText().empty())
224         m_join_widget->setActive(false);
225     else if (!m_join_widget->isActivated())
226         m_join_widget->setActive(true);
227 
228     // It's unsafe to delete from inside the event handler so we do it here
229     if (m_self_destroy)
230     {
231         ModalDialog::dismiss();
232         return;
233     }
234     if (m_join_server)
235         requestJoin();
236 }   // onUpdate
237