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