Add no-kart-selection network splitscreen

This commit is contained in:
Benau 2018-03-20 02:54:10 +08:00
parent cfd1de43bb
commit d436446de2
15 changed files with 439 additions and 53 deletions

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="5%" width="96%" height="85%" layout="vertical-row" >
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="Splitscreen player in network" text="Add player"/>
<spacer height="20" width="50"/>
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="Splitscreen player in network" text="Name"/>
<spinner id="name-spinner" width="50%" align="center" wrap_around="true" />
</div>
</div>
<spacer height="20" width="50"/>
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="Splitscreen player in network" text="Handicap"/>
<checkbox id="handicap" align="center" />
</div>
</div>
<spacer height="20" width="50"/>
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label id="error-message" proportion="1" text_align="left"/>
</div>
</div>
<spacer height="20" width="50"/>
<buttonbar id="options" width="90%" height="20%" align="center">
<icon-button id="add" width="64" height="64" icon="gui/blue_plus.png"
I18N="Splitscreen player in network" text="Add" label_location="bottom"/>
<icon-button id="connect" width="64" height="64" icon="gui/green_check.png"
I18N="Splitscreen player in network" text="Connect" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Splitscreen player in network" text="Cancel" label_location="bottom"/>
</buttonbar>
</div>
</stkgui>

@ -36,10 +36,12 @@
#include "modes/demo_world.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
#include "physics/physics.hpp"
#include "race/history.hpp"
#include "replay/replay_recorder.hpp"
#include "states_screens/dialogs/splitscreen_player_dialog.hpp"
#include "states_screens/kart_selection.hpp"
#include "states_screens/main_menu_screen.hpp"
#include "states_screens/options_screen_device.hpp"
@ -705,6 +707,27 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
// when a device presses fire or rescue
if (m_device_manager->getAssignMode() == DETECT_NEW)
{
if (NetworkConfig::get()->isAddingNetworkPlayers())
{
InputDevice *device = NULL;
if (type == Input::IT_KEYBOARD)
{
//Log::info("InputManager", "New Player Joining with Key %d", button);
device = m_device_manager->getKeyboardFromBtnID(button);
}
else if (type == Input::IT_STICKBUTTON ||
type == Input::IT_STICKMOTION )
{
device = m_device_manager->getGamePadFromIrrID(deviceID);
}
if (device && (action == PA_FIRE || action == PA_MENU_SELECT))
{
if (!GUIEngine::ModalDialog::isADialogActive())
new SplitscreenPlayerDialog(device);
return;
}
}
// Player is unjoining
if ((player != NULL) && (action == PA_RESCUE ||
action == PA_MENU_CANCEL ) )
@ -763,7 +786,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
// Prevent null pointer crash
return;
}
Log::info("","%s",StringUtils::wideToUtf8(player->getProfile()->getName()).c_str());
// Find the corresponding PlayerKart from our ActivePlayer instance
AbstractKart* pk = player->getKart();

@ -43,6 +43,7 @@ NetworkConfig::NetworkConfig()
m_auto_connect = false;
m_is_server = false;
m_is_public_server = false;
m_done_adding_network_players = false;
m_max_players = 4;
m_cur_user_id = 0;
m_cur_user_token = "";

@ -26,12 +26,17 @@
#include "race/race_manager.hpp"
#include "irrString.h"
#include <tuple>
#include <vector>
namespace Online
{
class XMLRequest;
}
class InputDevice;
class PlayerProfile;
class NetworkConfig
{
private:
@ -76,6 +81,8 @@ private:
* immediately start a race. */
bool m_auto_connect;
bool m_done_adding_network_players;
/** If this is a server, the server name. */
irr::core::stringw m_server_name;
@ -86,6 +93,9 @@ private:
/** Used by client server to determine if the child server is created. */
std::string m_server_id_file;
std::vector<std::tuple<InputDevice*, PlayerProfile*,
/*is_handicap*/bool> > m_network_players;
NetworkConfig();
public:
@ -170,6 +180,33 @@ public:
m_password = "";
}
// ------------------------------------------------------------------------
const std::vector<std::tuple<InputDevice*, PlayerProfile*, bool> >&
getNetworkPlayers() const { return m_network_players; }
// ------------------------------------------------------------------------
bool isAddingNetworkPlayers() const
{ return !m_done_adding_network_players; }
// ------------------------------------------------------------------------
void doneAddingNetworkPlayers() { m_done_adding_network_players = true; }
// ------------------------------------------------------------------------
bool addNetworkPlayer(InputDevice* device, PlayerProfile* profile, bool h)
{
for (auto& p : m_network_players)
{
if (std::get<0>(p) == device)
return false;
if (std::get<1>(p) == profile)
return false;
}
m_network_players.emplace_back(device, profile, h);
return true;
}
// ------------------------------------------------------------------------
void cleanNetworkPlayers()
{
m_network_players.clear();
m_done_adding_network_players = false;
}
// ------------------------------------------------------------------------
/** Sets the maximum number of players for this server. */
void setMaxPlayers(unsigned n) { m_max_players = n; }
// ------------------------------------------------------------------------

@ -243,30 +243,37 @@ void ClientLobby::update(float dt)
break;
case LINKED:
{
// atm assume only 1 local player (no split screen yet)
NetworkString *ns = getNetworkString();
ns->addUInt8(LE_CONNECTION_REQUESTED)
.encodeString(NetworkConfig::get()->getPassword());
uint8_t num_player = 1;
ns->addUInt8(num_player);
for (unsigned i = 0; i < num_player; i++)
assert(!NetworkConfig::get()->isAddingNetworkPlayers());
ns->addUInt8(
(uint8_t)NetworkConfig::get()->getNetworkPlayers().size());
// Only first player has online name and profile
bool first_player = true;
for (auto& p : NetworkConfig::get()->getNetworkPlayers())
{
core::stringw name;
PlayerProfile* player = PlayerManager::getCurrentPlayer();
PlayerProfile* player = std::get<1>(p);
if (PlayerManager::getCurrentOnlineState() ==
PlayerProfile::OS_SIGNED_IN)
PlayerProfile::OS_SIGNED_IN && first_player)
{
name = PlayerManager::getCurrentOnlineUserName();
}
else
{
name = player->getName();
}
std::string name_u8 = StringUtils::wideToUtf8(name);
ns->encodeString(name_u8).addFloat(player->getDefaultKartColor());
Online::OnlinePlayerProfile* opp =
dynamic_cast<Online::OnlinePlayerProfile*>(player);
ns->addUInt32(opp && opp->getProfile() ?
ns->addUInt32(first_player && opp && opp->getProfile() ?
opp->getProfile()->getID() : 0);
// Assume no handicap player now
ns->addUInt8(PLAYER_DIFFICULTY_NORMAL);
// Per-player handicap
ns->addUInt8(std::get<2>(p));
first_player = false;
}
auto all_k = kart_properties_manager->getAllAvailableKarts();
auto all_t = track_manager->getAllTrackIdentifiers();
@ -397,8 +404,9 @@ void ClientLobby::connectionAccepted(Event* event)
Log::info("ClientLobby", "The server accepted the connection.");
STKHost::get()->setMyHostId(data.getUInt32());
// For now no split screen so only 1 player
m_game_setup->setNumLocalPlayers(1);
assert(!NetworkConfig::get()->isAddingNetworkPlayers());
m_game_setup->setNumLocalPlayers((int)
NetworkConfig::get()->getNetworkPlayers().size());
// connection token
uint32_t token = data.getToken();
peer->setClientServerToken(token);

@ -26,7 +26,6 @@
#include "network/network_console.hpp"
#include "network/network_string.hpp"
#include "network/protocols/connect_to_peer.hpp"
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/protocol_manager.hpp"
#include "network/stk_peer.hpp"
@ -80,7 +79,6 @@ void STKHost::create(std::shared_ptr<Server> server, SeparateProcess* p)
else
{
m_stk_host = new STKHost(server);
std::make_shared<ConnectToServer>(server)->requestStart();
}
m_stk_host->m_separate_process = p;
if (!m_stk_host->m_network)

@ -263,7 +263,7 @@ void CreateServerScreen::createServer()
new SeparateProcess(SeparateProcess::getCurrentExecutableLocation(),
server_cfg.str() + password);
STKHost::create(server, sp);
NetworkingLobby::getInstance()->setJoinedServer(server);
#endif
} // createServer

@ -42,9 +42,6 @@ void NetworkUserDialog::beforeAddingWidgets()
assert(m_name_widget != NULL);
m_name_widget->setText(m_name, false);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_friend_widget = getWidget<IconButtonWidget>("friend");
assert(m_friend_widget != NULL);
m_friend_widget->setVisible(m_online_id != 0);

@ -0,0 +1,128 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 SuperTuxKart-Team
//
// 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 "states_screens/dialogs/splitscreen_player_dialog.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "input/device_manager.hpp"
#include "input/input_manager.hpp"
#include "guiengine/dialog_queue.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/message_queue.hpp"
#include "network/network_config.hpp"
#include "states_screens/networking_lobby.hpp"
#include "utils/translation.hpp"
#include <IGUIEnvironment.h>
using namespace GUIEngine;
using namespace irr;
using namespace irr::gui;
using namespace Online;
// ----------------------------------------------------------------------------
SplitscreenPlayerDialog::~SplitscreenPlayerDialog()
{
if (!m_connect_now)
{
input_manager->getDeviceManager()->setAssignMode(DETECT_NEW);
input_manager->getDeviceManager()->mapFireToSelect(true);
}
} // ~SplitscreenPlayerDialog
// ----------------------------------------------------------------------------
void SplitscreenPlayerDialog::beforeAddingWidgets()
{
m_profiles = getWidget<SpinnerWidget>("name-spinner");
for (unsigned i = 0; i < PlayerManager::get()->getNumPlayers(); i++)
m_profiles->addLabel(PlayerManager::get()->getPlayer(i)->getName());
m_error_message = getWidget<LabelWidget>("error-message");
m_handicap = getWidget<CheckBoxWidget>("handicap");
m_handicap->setState(false);
m_handicap->setActive(UserConfigParams::m_per_player_difficulty);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_add = getWidget<IconButtonWidget>("add");
assert(m_add != NULL);
m_connect = getWidget<IconButtonWidget>("connect");
assert(m_connect != NULL);
m_cancel = getWidget<IconButtonWidget>("cancel");
assert(m_cancel != NULL);
input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
input_manager->getDeviceManager()->mapFireToSelect(false);
} // beforeAddingWidgets
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation
SplitscreenPlayerDialog::processEvent(const std::string& source)
{
if (source == m_options_widget->m_properties[PROP_ID])
{
const std::string& selection = m_options_widget
->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == m_add->m_properties[PROP_ID])
{
const unsigned pid = m_profiles->getValue();
assert(pid < PlayerManager::get()->getNumPlayers());
PlayerProfile* p = PlayerManager::get()->getPlayer(pid);
const bool handicap = m_handicap->getState();
if (NetworkConfig::get()->addNetworkPlayer(m_device, p, handicap))
{
NetworkingLobby::getInstance()
->addSplitscreenPlayer(p->getName());
m_self_destroy = true;
return GUIEngine::EVENT_BLOCK;
}
else
{
//I18N: in splitscreen player dialog for network game
m_error_message->setErrorColor();
m_error_message->setText(_("Player already exists."), false);
}
return GUIEngine::EVENT_BLOCK;
}
else if(selection == m_connect->m_properties[PROP_ID])
{
if (!NetworkConfig::get()->getNetworkPlayers().empty())
{
NetworkConfig::get()->doneAddingNetworkPlayers();
NetworkingLobby::getInstance()->finishAddingPlayers();
m_connect_now = true;
m_self_destroy = true;
return GUIEngine::EVENT_BLOCK;
}
//I18N: in splitscreen player dialog for network game
m_error_message->setErrorColor();
m_error_message->setText(_("No player available to connect."),
false);
return GUIEngine::EVENT_BLOCK;
}
else if(selection == m_cancel->m_properties[PROP_ID])
{
m_self_destroy = true;
return GUIEngine::EVENT_BLOCK;
}
}
return GUIEngine::EVENT_LET;
} // processEvent

@ -0,0 +1,90 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 SuperTuxKart-Team
//
// 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_SPLITSCREEN_PLAYER_DIALOG_HPP
#define HEADER_SPLITSCREEN_PLAYER_DIALOG_HPP
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets.hpp"
#include "utils/types.hpp"
#include <irrString.h>
class InputDevice;
/**
* \brief Dialog that handle user in network lobby
* \ingroup states_screens
*/
class SplitscreenPlayerDialog : public GUIEngine::ModalDialog
{
private:
InputDevice* m_device;
bool m_self_destroy;
bool m_connect_now;
GUIEngine::LabelWidget* m_error_message;
GUIEngine::SpinnerWidget* m_profiles;
GUIEngine::CheckBoxWidget* m_handicap;
GUIEngine::RibbonWidget* m_options_widget;
GUIEngine::IconButtonWidget* m_add;
GUIEngine::IconButtonWidget* m_connect;
GUIEngine::IconButtonWidget* m_cancel;
public:
SplitscreenPlayerDialog(InputDevice* device)
: ModalDialog(0.8f,0.8f), m_device(device), m_self_destroy(false),
m_connect_now(false)
{
loadFromFile("online/splitscreen_player_dialog.stkgui");
}
// ------------------------------------------------------------------------
~SplitscreenPlayerDialog();
// ------------------------------------------------------------------------
virtual void beforeAddingWidgets();
// ------------------------------------------------------------------------
void onEnterPressedInternal() { m_self_destroy = true; }
// ------------------------------------------------------------------------
GUIEngine::EventPropagation processEvent(const std::string& source);
// ------------------------------------------------------------------------
virtual bool onEscapePressed()
{
m_self_destroy = true;
return false;
}
// ------------------------------------------------------------------------
virtual void onUpdate(float dt)
{
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
ModalDialog::dismiss();
return;
}
}
};
#endif

@ -37,6 +37,7 @@
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "modes/overworld.hpp"
#include "network/network_config.hpp"
#include "states_screens/race_setup_screen.hpp"
#include "utils/log.hpp"
#include "utils/translation.hpp"
@ -340,7 +341,8 @@ void KartSelectionScreen::init()
tabs->setActive(true);
m_kart_widgets.clearAndDeleteAll();
StateManager::get()->resetActivePlayers();
if (NetworkConfig::get()->getNetworkPlayers().empty())
StateManager::get()->resetActivePlayers();
input_manager->getDeviceManager()->setAssignMode(DETECT_NEW);
DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");

@ -123,6 +123,7 @@ void MainMenuScreen::init()
assert(m_user_id);
// reset in case we're coming back from a race
NetworkConfig::get()->cleanNetworkPlayers();
StateManager::get()->resetActivePlayers();
input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
input_manager->getDeviceManager()->setSinglePlayer( NULL );

@ -165,6 +165,7 @@ void NetworkKartSelectionScreen::tearDown()
bool NetworkKartSelectionScreen::onEscapePressed()
{
// then remove the lobby screen (you left the server)
StateManager::get()->resetActivePlayers();
StateManager::get()->popMenu();
STKHost::get()->shutdown();
input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);

@ -34,6 +34,7 @@
#include "io/file_manager.hpp"
#include "network/network_config.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/server.hpp"
#include "network/stk_host.hpp"
@ -115,30 +116,37 @@ void NetworkingLobby::beforeAddingWidget()
void NetworkingLobby::init()
{
Screen::init();
// Already connected
if (LobbyProtocol::get<LobbyProtocol>())
return;
m_server_info_height = GUIEngine::getFont()->getDimension(L"X").Height;
m_start_button->setVisible(false);
getWidget("chat")->setVisible(false);
getWidget("chat")->setActive(false);
getWidget("send")->setVisible(false);
getWidget("send")->setActive(false);
// For now create the active player and bind it to the right
// input device.
InputDevice* device =
input_manager->getDeviceManager()->getLatestUsedDevice();
PlayerProfile* profile = PlayerManager::getCurrentPlayer();
StateManager::get()->createActivePlayer(profile, device);
if (!UserConfigParams::m_lobby_chat)
if (NetworkConfig::get()->getNetworkPlayers().empty())
{
getWidget("chat")->setVisible(false);
getWidget("chat")->setActive(false);
getWidget("send")->setVisible(false);
getWidget("send")->setActive(false);
m_state = LS_ADD_PLAYERS;
input_manager->getDeviceManager()->mapFireToSelect(true);
input_manager->getDeviceManager()->setAssignMode(DETECT_NEW);
}
else
else if (NetworkConfig::get()->isClient())
{
m_chat_box->addListener(this);
getWidget("chat")->setVisible(true);
getWidget("chat")->setActive(true);
getWidget("send")->setVisible(true);
getWidget("send")->setActive(true);
// In case players had already configured connect now
m_state = LS_CONNECTING;
std::make_shared<ConnectToServer>(m_joined_server)->requestStart();
if (UserConfigParams::m_lobby_chat)
{
m_chat_box->clearListeners();
m_chat_box->addListener(this);
getWidget("chat")->setVisible(true);
getWidget("chat")->setActive(true);
getWidget("send")->setVisible(true);
getWidget("send")->setActive(true);
}
}
} // init
@ -208,6 +216,17 @@ void NetworkingLobby::addMoreServerInfo(core::stringw info)
// ----------------------------------------------------------------------------
void NetworkingLobby::onUpdate(float delta)
{
if (m_state == LS_ADD_PLAYERS && NetworkConfig::get()->isClient())
{
m_text_bubble->setText(_("Everyone:\nPress the 'Select' button to "
"join the game"), true);
m_start_button->setVisible(false);
m_exit_widget->setVisible(false);
return;
}
m_start_button->setVisible(false);
m_exit_widget->setVisible(true);
auto lp = LobbyProtocol::get<LobbyProtocol>();
if (!lp)
{
@ -304,19 +323,11 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
}
else if (selection == m_start_button->m_properties[PROP_ID])
{
if (NetworkConfig::get()->isServer())
{
auto slrp = LobbyProtocol::get<ServerLobby>();
slrp->startSelection();
}
else
{
// Send a message to the server to start
NetworkString start(PROTOCOL_LOBBY_ROOM);
start.setSynchronous(true);
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
STKHost::get()->sendToServer(&start, true);
}
// Send a message to the server to start
NetworkString start(PROTOCOL_LOBBY_ROOM);
start.setSynchronous(true);
start.addUInt8(LobbyProtocol::LE_REQUEST_BEGIN);
STKHost::get()->sendToServer(&start, true);
}
} // eventCallback
@ -328,14 +339,26 @@ void NetworkingLobby::unloaded()
} // unloaded
// ----------------------------------------------------------------------------
void NetworkingLobby::tearDown()
{
// Server has a dummy network lobby too
if (!NetworkConfig::get()->isClient())
return;
input_manager->getDeviceManager()->mapFireToSelect(false);
assert(!NetworkConfig::get()->isAddingNetworkPlayers());
StateManager::get()->resetActivePlayers();
for (auto& p : NetworkConfig::get()->getNetworkPlayers())
{
StateManager::get()->createActivePlayer(std::get<1>(p),
std::get<0>(p));
}
} // tearDown
// ----------------------------------------------------------------------------
bool NetworkingLobby::onEscapePressed()
{
input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
input_manager->getDeviceManager()->mapFireToSelect(false);
STKHost::get()->shutdown();
return true; // close the screen
} // onEscapePressed
@ -366,4 +389,30 @@ void NetworkingLobby::updatePlayers(const std::vector<std::tuple<uint32_t,
StringUtils::toString(std::get<1>(q));
m_player_list->addItem(internal_name, std::get<2>(q), std::get<3>(q));
}
} // updatePlayers
} // updatePlayers
// ----------------------------------------------------------------------------
void NetworkingLobby::addSplitscreenPlayer(irr::core::stringw name)
{
if (!m_player_list)
return;
m_player_list->setIcons(m_icon_bank);
m_player_list->addItem(StringUtils::wideToUtf8(name), name, 1);
} // addSplitscreenPlayer
// ----------------------------------------------------------------------------
void NetworkingLobby::finishAddingPlayers()
{
m_state = LS_CONNECTING;
std::make_shared<ConnectToServer>(m_joined_server)->requestStart();
m_start_button->setVisible(false);
if (UserConfigParams::m_lobby_chat)
{
m_chat_box->clearListeners();
m_chat_box->addListener(this);
getWidget("chat")->setVisible(true);
getWidget("chat")->setActive(true);
getWidget("send")->setVisible(true);
getWidget("send")->setActive(true);
}
} // finishAddingPlayers

@ -51,6 +51,12 @@ class NetworkingLobby : public GUIEngine::Screen,
public GUIEngine::ITextBoxWidgetListener
{
private:
enum LobbyState
{
LS_ADD_PLAYERS,
LS_CONNECTING
} m_state;
friend class GUIEngine::ScreenSingleton<NetworkingLobby>;
NetworkingLobby();
@ -104,12 +110,14 @@ public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual bool onEscapePressed() OVERRIDE;
/** Used to insert each client chat message (reserved). */
void finishAddingPlayers();
void addMoreServerInfo(core::stringw info);
void setJoinedServer(std::shared_ptr<Server> server);
void updatePlayers(const std::vector<std::tuple<uint32_t/*host id*/,
uint32_t/*online id*/, core::stringw/*player name*/,
int/*icon id*/> >& p);
void addSplitscreenPlayer(irr::core::stringw name);
}; // class NetworkingLobby
#endif