diff --git a/data/gui/karts_online.stkgui b/data/gui/karts_online.stkgui
deleted file mode 100644
index 03c349e27..000000000
--- a/data/gui/karts_online.stkgui
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<stkgui>
-    <div x="1%" y="1%" width="98%" height="99%" layout="vertical-row" >
-
-        <header width="80%"
-               I18N="In the kart selection (player setup) screen"
-               text="Choose a Kart"
-               align="center" text_align="center" />
-
-        <placeholder id="playerskarts" width="100%" align="center" proportion="4">
-            <!-- Contents is added programatically -->
-        </placeholder>
-
-        <spacer height="15" width="25"/>
-
-        <box proportion="2" width="100%" layout="vertical-row" padding="2">
-            <ribbon_grid id="karts" proportion="1" square_items="true" width="100%" align="center"
-                         child_width="90" child_height="90" max_rows="3"/>
-        </box>
-
-        <!-- Groups will be added dynamically at runtime -->
-        <tabs width="98%" x="1%" height="25" id="kartgroups">
-        </tabs>
-        <spacer width="100%" height="2%"/>
-    </div>
-
-    <icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
-</stkgui>
diff --git a/src/guiengine/widgets/player_kart_widget.hpp b/src/guiengine/widgets/player_kart_widget.hpp
index 66474c857..073354da4 100644
--- a/src/guiengine/widgets/player_kart_widget.hpp
+++ b/src/guiengine/widgets/player_kart_widget.hpp
@@ -108,7 +108,9 @@ namespace GUIEngine
         // ------------------------------------------------------------------------
         /** Called when players are renumbered (changes the player ID) */
         void setPlayerID(const int newPlayerID);
-
+        // ------------------------------------------------------------------------
+        PlayerNameSpinner* getPlayerNameSpinner() const
+                                                 { return m_player_ident_spinner; }
         // ------------------------------------------------------------------------
         /** Returns the ID of this player */
         int getPlayerID() const;
diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp
index c64bb94e6..b82629fa7 100644
--- a/src/input/input_manager.cpp
+++ b/src/input/input_manager.cpp
@@ -712,7 +712,8 @@ 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())
+            if (NetworkConfig::get()->isNetworking() &&
+                NetworkConfig::get()->isAddingNetworkPlayers())
             {
                 // Ignore release event
                 if (value == 0)
@@ -775,7 +776,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
 
                     if (device != NULL)
                     {
-                        KartSelectionScreen::getRunningInstance()->joinPlayer(device);
+                        KartSelectionScreen::getRunningInstance()->joinPlayer(device, NULL/*player profile*/);
                     }
                 }
                 return; // we're done here, ignore devices that aren't
diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp
index 5bfd4ae1b..c00ae1b80 100644
--- a/src/network/protocols/client_lobby.cpp
+++ b/src/network/protocols/client_lobby.cpp
@@ -20,9 +20,10 @@
 
 #include "config/user_config.hpp"
 #include "config/player_manager.hpp"
-#include "karts/kart_properties_manager.hpp"
 #include "guiengine/modaldialog.hpp"
 #include "guiengine/message_queue.hpp"
+#include "input/device_manager.hpp"
+#include "karts/kart_properties_manager.hpp"
 #include "modes/world_with_rank.hpp"
 #include "network/event.hpp"
 #include "network/game_setup.hpp"
@@ -72,11 +73,21 @@ ClientLobby::ClientLobby() : LobbyProtocol(NULL)
 }   // ClientLobby
 
 //-----------------------------------------------------------------------------
-
 ClientLobby::~ClientLobby()
 {
+    clearPlayers();
 }   // ClientLobby
 
+//-----------------------------------------------------------------------------
+void ClientLobby::clearPlayers()
+{
+    StateManager::get()->resetActivePlayers();
+    input_manager->getDeviceManager()->setAssignMode(NO_ASSIGN);
+    input_manager->getDeviceManager()->setSinglePlayer(NULL);
+    input_manager->setMasterPlayerOnly(false);
+    input_manager->getDeviceManager()->clearLatestUsedDevice();
+}   // clearPlayers
+
 //-----------------------------------------------------------------------------
 /** Sets the address of the server. 
  */
@@ -84,10 +95,12 @@ void ClientLobby::setAddress(const TransportAddress &address)
 {
     m_server_address.copy(address);
 }   // setAddress
-//-----------------------------------------------------------------------------
 
+//-----------------------------------------------------------------------------
 void ClientLobby::setup()
 {
+    clearPlayers();
+    TracksScreen::getInstance()->resetVote();
     LobbyProtocol::setup();
     m_state = NONE;
 }   // setup
@@ -304,11 +317,27 @@ void ClientLobby::update(int ticks)
     {
         // In case the user opened a user info dialog
         GUIEngine::ModalDialog::dismiss();
-        TracksScreen::getInstance()->resetVote();
         NetworkKartSelectionScreen* screen =
-                                     NetworkKartSelectionScreen::getInstance();
+            NetworkKartSelectionScreen::getInstance();
         screen->setAvailableKartsFromServer(m_available_karts);
-        screen->push();
+        // In case of auto-connect, use random karts (or previous kart) from
+        // server and go to track selection (or grand prix later)
+        if (NetworkConfig::get()->isAutoConnect())
+        {
+            input_manager->setMasterPlayerOnly(true);
+            for (auto& p : NetworkConfig::get()->getNetworkPlayers())
+            {
+                StateManager::get()
+                    ->createActivePlayer(std::get<1>(p), std::get<0>(p));
+            }
+            input_manager->getDeviceManager()->setAssignMode(ASSIGN);
+            TracksScreen::getInstance()->setNetworkTracks();
+            TracksScreen::getInstance()->push();
+        }
+        else
+        {
+            screen->push();
+        }
         m_state = SELECTING_KARTS;
         std::make_shared<LatencyProtocol>()->requestStart();
         Log::info("LobbyProtocol", "LatencyProtocol started.");
@@ -620,17 +649,18 @@ void ClientLobby::raceFinished(Event* event)
  */
 void ClientLobby::exitResultScreen(Event *event)
 {
-    RaceResultGUI::getInstance()->backToLobby();
-    // Will be reset to linked if connected to server, see update(float dt)
-    LobbyProtocol::setup();
-    STKHost::get()->getServerPeerForClient()->unsetClientServerToken();
     // stop race protocols
     auto pm = ProtocolManager::lock();
     assert(pm);
     pm->findAndTerminate(PROTOCOL_CONTROLLER_EVENTS);
     pm->findAndTerminate(PROTOCOL_KART_UPDATE);
     pm->findAndTerminate(PROTOCOL_GAME_EVENTS);
-    m_state = NONE;
+
+    // Will be reset to linked if connected to server, see update(float dt)
+    setup();
+
+    RaceResultGUI::getInstance()->backToLobby();
+    STKHost::get()->getServerPeerForClient()->unsetClientServerToken();
 }   // exitResultScreen
 
 //-----------------------------------------------------------------------------
diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp
index ed0ccb9ed..06ea1037a 100644
--- a/src/network/protocols/client_lobby.hpp
+++ b/src/network/protocols/client_lobby.hpp
@@ -22,6 +22,8 @@ private:
     void handleChat(Event* event);
     void becomingServerOwner();
 
+    void clearPlayers();
+
     TransportAddress m_server_address;
 
     enum STATE
diff --git a/src/states_screens/kart_selection.cpp b/src/states_screens/kart_selection.cpp
index de0d937e1..70236d4d3 100644
--- a/src/states_screens/kart_selection.cpp
+++ b/src/states_screens/kart_selection.cpp
@@ -341,9 +341,6 @@ void KartSelectionScreen::init()
     tabs->setActive(true);
 
     m_kart_widgets.clearAndDeleteAll();
-    if (NetworkConfig::get()->getNetworkPlayers().empty())
-        StateManager::get()->resetActivePlayers();
-    input_manager->getDeviceManager()->setAssignMode(DETECT_NEW);
 
     DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");
     assert( w != NULL );
@@ -380,26 +377,32 @@ void KartSelectionScreen::init()
     }
     else */
     // For now this is what will happen
-    if (!m_multiplayer)
+    input_manager->getDeviceManager()->setAssignMode(DETECT_NEW);
+    if (!NetworkConfig::get()->isNetworking())
     {
-        joinPlayer(input_manager->getDeviceManager()->getLatestUsedDevice());
-        w->updateItemDisplay();
-
-        // Player 0 select default kart
-        if (!w->setSelection(UserConfigParams::m_default_kart, 0, true))
+        if (!m_multiplayer)
         {
-            // if kart from config not found, select the first instead
-            w->setSelection(0, 0, true);
+            joinPlayer(input_manager->getDeviceManager()->getLatestUsedDevice(),
+                NULL/*player profile*/);
+            w->updateItemDisplay();
+
+            // Player 0 select default kart
+            if (!w->setSelection(UserConfigParams::m_default_kart, 0, true))
+            {
+                // if kart from config not found, select the first instead
+                w->setSelection(0, 0, true);
+            }
         }
-    } else
-        // Add multiplayer message
-        addMultiplayerMessage();
-
-    // This flag will cause that a 'fire' event will be mapped to 'select' (if
-    // 'fire' is not assigned to a GUI event). This is done to support the old
-    // way of player joining by pressing 'fire' instead of 'select'.
-    input_manager->getDeviceManager()->mapFireToSelect(true);
-
+        else
+        {
+            // Add multiplayer message
+            addMultiplayerMessage();
+        }
+        // This flag will cause that a 'fire' event will be mapped to 'select' (if
+        // 'fire' is not assigned to a GUI event). This is done to support the old
+        // way of player joining by pressing 'fire' instead of 'select'.
+        input_manager->getDeviceManager()->mapFireToSelect(true);
+    }
 }   // init
 
 // ----------------------------------------------------------------------------
@@ -437,7 +440,7 @@ void KartSelectionScreen::unloaded()
 
 // ----------------------------------------------------------------------------
 // Return true if event was handled successfully
-bool KartSelectionScreen::joinPlayer(InputDevice* device)
+bool KartSelectionScreen::joinPlayer(InputDevice* device, PlayerProfile* p)
 {
     bool first_player = m_kart_widgets.size() == 0;
 
@@ -470,14 +473,18 @@ bool KartSelectionScreen::joinPlayer(InputDevice* device)
     }
 
     // ---- Create new active player
-    PlayerProfile* profile_to_use = PlayerManager::getCurrentPlayer();
+    PlayerProfile* profile_to_use = p == NULL ?
+        PlayerManager::getCurrentPlayer() : p;
 
     // Make sure enough guest character exists. At this stage this player has
     // not been added, so the number of guests requested for the first player
     // is 0 --> forcing at least one real player.
-    PlayerManager::get()->createGuestPlayers(
-                                     StateManager::get()->activePlayerCount());
-    if (!first_player)
+    if (p == NULL)
+    {
+        PlayerManager::get()->createGuestPlayers(
+            StateManager::get()->activePlayerCount());
+    }
+    if (!first_player && p == NULL)
     {
         // Give each player a different start profile
         const int num_active_players = StateManager::get()->activePlayerCount();
@@ -516,6 +523,12 @@ bool KartSelectionScreen::joinPlayer(InputDevice* device)
     m_kart_widgets.push_back(newPlayerWidget);
 
     newPlayerWidget->add();
+    // From network kart selection, the player name is already defined
+    if (p != NULL)
+    {
+        newPlayerWidget->getPlayerNameSpinner()->setActive(false);
+        newPlayerWidget->getPlayerNameSpinner()->setCustomText(p->getName());
+    }
 
     // ---- Divide screen space among all karts
     const int amount = m_kart_widgets.size();
@@ -524,7 +537,8 @@ bool KartSelectionScreen::joinPlayer(InputDevice* device)
     // in this special case, leave room for a message on the right
     if (m_multiplayer && first_player)
     {
-        addMultiplayerMessage();
+        if (p == NULL)
+            addMultiplayerMessage();
         const int splitWidth = fullarea->m_w / 2;
         m_kart_widgets[0].move( fullarea->m_x, fullarea->m_y, splitWidth,
                                 fullarea->m_h );
@@ -1483,7 +1497,7 @@ void KartSelectionScreen::setKartsFromCurrentGroup()
     {
         const KartProperties* prop = karts.get(i);
         if (PlayerManager::getCurrentPlayer()->isLocked(prop->getIdent()) &&
-            !m_multiplayer)
+            !m_multiplayer && !NetworkConfig::get()->isNetworking())
         {
             w->addItem(_("Locked : solve active challenges to gain access to more!"),
                        ID_LOCKED + prop->getIdent(),
diff --git a/src/states_screens/kart_selection.hpp b/src/states_screens/kart_selection.hpp
index 7d21621e1..cd1c94e3d 100644
--- a/src/states_screens/kart_selection.hpp
+++ b/src/states_screens/kart_selection.hpp
@@ -38,6 +38,7 @@ namespace Online
 
 class FocusDispatcher;
 class InputDevice;
+class PlayerProfile;
 class KartHoverListener;
 
 extern int g_root_id;
@@ -85,7 +86,7 @@ protected:
     KartSelectionScreen(const char* filename);
 
     /** Called when all players selected their kart */
-    void allPlayersDone();
+    virtual void allPlayersDone();
 
     /** Called when number/order of karts changed, so that all will keep
      *  an up-to-date ID */
@@ -105,7 +106,7 @@ protected:
     /** Fill the ribbon with the karts from the currently selected group */
     void setKartsFromCurrentGroup();
 
-    virtual void playerConfirm(const int playerID);
+    void playerConfirm(const int playerID);
 
     void updateKartStats(uint8_t widget_id,
                          const std::string& selection);
@@ -143,14 +144,14 @@ public:
 
     /** \brief Called when a player hits 'fire'/'select' on his device to
      *  join the game */
-    bool joinPlayer(InputDevice* device);
+    bool joinPlayer(InputDevice* device, PlayerProfile* p);
 
     /**
       * \brief Called when a player hits 'rescue'/'cancel' on his device
       *  to leave the game
       * \return true if event was handled succesfully
       */
-    bool playerQuit(StateManager::ActivePlayer* player);
+    virtual bool playerQuit(StateManager::ActivePlayer* player);
 
      /** \brief implement callback from parent class GUIEngine::Screen */
     virtual void init() OVERRIDE;
diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp
index a87abc6b4..6eef64376 100644
--- a/src/states_screens/main_menu_screen.cpp
+++ b/src/states_screens/main_menu_screen.cpp
@@ -150,8 +150,6 @@ void MainMenuScreen::init()
         w->setBadge(LOADING_BADGE);
     }
 
-    IconButtonWidget* online = getWidget<IconButtonWidget>("online");
-
     LabelWidget* w = getWidget<LabelWidget>("info_addons");
     const core::stringw &news_text = NewsManager::get()->getNextNewsMessage();
     w->setText(news_text, true);
diff --git a/src/states_screens/network_kart_selection.cpp b/src/states_screens/network_kart_selection.cpp
index 8640c3cae..afe63d4bc 100644
--- a/src/states_screens/network_kart_selection.cpp
+++ b/src/states_screens/network_kart_selection.cpp
@@ -17,157 +17,92 @@
 
 #include "states_screens/network_kart_selection.hpp"
 
-#include "audio/sfx_manager.hpp"
-#include "challenges/unlock_manager.hpp"
-#include "config/player_manager.hpp"
 #include "config/user_config.hpp"
-#include "graphics/irr_driver.hpp"
-#include "guiengine/widgets/player_kart_widget.hpp"
 #include "input/device_manager.hpp"
-#include "items/item_manager.hpp"
-#include "karts/kart_properties.hpp"
-#include "karts/kart_properties_manager.hpp"
-#include "network/game_setup.hpp"
 #include "network/network_config.hpp"
-#include "network/network_player_profile.hpp"
-#include "network/protocol_manager.hpp"
-#include "network/protocols/client_lobby.hpp"
+#include "network/protocols/lobby_protocol.hpp"
 #include "network/stk_host.hpp"
-#include "states_screens/race_setup_screen.hpp"
 #include "states_screens/state_manager.hpp"
 #include "states_screens/tracks_screen.hpp"
 
-static const char ID_LOCKED[] = "locked/";
-
 using namespace GUIEngine;
 
 DEFINE_SCREEN_SINGLETON( NetworkKartSelectionScreen );
 
-NetworkKartSelectionScreen::NetworkKartSelectionScreen()
-                          : KartSelectionScreen("karts_online.stkgui")
-{
-}   // NetworkKartSelectionScreen
-
-// ----------------------------------------------------------------------------
-NetworkKartSelectionScreen::~NetworkKartSelectionScreen()
-{
-}   // ~NetworkKartSelectionScreen
-
 // ----------------------------------------------------------------------------
 void NetworkKartSelectionScreen::init()
 {
-    m_multiplayer = false;
+    assert(!NetworkConfig::get()->isAddingNetworkPlayers());
+    m_multiplayer = NetworkConfig::get()->getNetworkPlayers().size() != 1;
     KartSelectionScreen::init();
 
     RibbonWidget* tabs = getWidget<RibbonWidget>("kartgroups");
-    assert( tabs != NULL );
-    // Select standard kart group
-    tabs->select( "standard", PLAYER_ID_GAME_MASTER);
-    tabs->setActive(false);
-    tabs->setVisible(false);
+    assert(tabs != NULL);
 
     // change the back button image (because it makes the game quit)
     IconButtonWidget* back_button = getWidget<IconButtonWidget>("back");
     back_button->setImage("gui/main_quit.png");
 
-    // add a widget for each player except self (already exists):
-    GameSetup* game_setup = LobbyProtocol::get<LobbyProtocol>()->getGameSetup();
-    if (!game_setup)
+    DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");
+    assert(w != NULL);
+    for (auto& p : NetworkConfig::get()->getNetworkPlayers())
     {
-        Log::error("NetworkKartSelectionScreen",
-                   "No network game setup registered.");
-        return;
+        joinPlayer(std::get<0>(p), std::get<1>(p));
+        w->updateItemDisplay();
+        if (!w->setSelection(UserConfigParams::m_default_kart, 0, true))
+        {
+            // if kart from config not found, select the first instead
+            w->setSelection(0, 0, true);
+        }
     }
-    // ---- Get available area for karts
-    // make a copy of the area, ands move it to be outside the screen
-    Widget* kartsAreaWidget = getWidget("playerskarts");
-    // start at the rightmost of the screen
-    const int shift = irr_driver->getFrameSize().Width;
-    core::recti kartsArea(kartsAreaWidget->m_x + shift,
-                            kartsAreaWidget->m_y,
-                            kartsAreaWidget->m_x + shift + kartsAreaWidget->m_w,
-                            kartsAreaWidget->m_y + kartsAreaWidget->m_h);
-
-    // FIXME: atm only adds the local master, split screen supports
-    // needs to be added
-    int player_id = game_setup->getLocalMasterID();
-    m_id_mapping.clear();
-    m_id_mapping.insert(m_id_mapping.begin(), player_id);
-
-    const int amount = m_kart_widgets.size();
-    Widget* fullarea = getWidget("playerskarts");
-
-    const int splitWidth = fullarea->m_w / amount;
-
-    for (int n=0; n<amount; n++)
-    {
-        m_kart_widgets[n].move( fullarea->m_x + splitWidth*n,
-                                fullarea->m_y, splitWidth, fullarea->m_h);
-    }
-    // In case of auto-connect, select default kart and go to track selection.
-    if (NetworkConfig::get()->isAutoConnect())
-    {
-        DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");
-        assert(w != NULL);
-        w->setSelection(UserConfigParams::m_default_kart, /*player id*/0, /*focus*/true);
-        playerConfirm(0);
-    }
-
 }   // init
 
 // ----------------------------------------------------------------------------
-void NetworkKartSelectionScreen::playerConfirm(const int playerID)
+void NetworkKartSelectionScreen::allPlayersDone()
 {
-    DynamicRibbonWidget* w = getWidget<DynamicRibbonWidget>("karts");
-    assert(w != NULL);
-    const std::string selection = w->getSelectionIDString(playerID);
-    if (StringUtils::startsWith(selection, ID_LOCKED))
+    input_manager->setMasterPlayerOnly(true);
+
+    RibbonWidget* tabs = getWidget<RibbonWidget>("kartgroups");
+    assert(tabs != NULL);
+
+    std::string selected_kart_group =
+        tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER);
+
+    UserConfigParams::m_last_used_kart_group = selected_kart_group;
+
+    const PtrVector<StateManager::ActivePlayer, HOLD>& players =
+        StateManager::get()->getActivePlayers();
+    for (unsigned int n = 0; n < players.size(); n++)
     {
-        unlock_manager->playLockSound();
-        return;
+        StateManager::get()->getActivePlayer(n)->getProfile()
+            ->incrementUseFrequency();
     }
 
-    if (playerID == PLAYER_ID_GAME_MASTER)
+    const uint8_t kart_count = (uint8_t)m_kart_widgets.size();
+    NetworkString kart(PROTOCOL_LOBBY_ROOM);
+    kart.addUInt8(LobbyProtocol::LE_KART_SELECTION).addUInt8(kart_count);
+    for (unsigned n = 0; n < kart_count; n++)
     {
-        UserConfigParams::m_default_kart = selection;
+        // If server recieve an invalid name, it will auto correct to a random
+        // kart
+        kart.encodeString(m_kart_widgets[n].m_kartInternalName);
     }
+    STKHost::get()->sendToServer(&kart, true);
 
-    if (m_kart_widgets[playerID].getKartInternalName().size() == 0)
-    {
-        SFXManager::get()->quickSound( "anvil" );
-        return;
-    }
-    if (playerID == PLAYER_ID_GAME_MASTER) // self
-    {
-        // FIXME SPLITSCREEN: we need to supply the global player id of the 
-        // player selecting the kart here. For now ... just vote the same kart
-        // for each local player.
-        uint8_t player_count = 1;
-        NetworkString kart(PROTOCOL_LOBBY_ROOM);
-        kart.addUInt8(LobbyProtocol::LE_KART_SELECTION).addUInt8(player_count)
-            .encodeString(selection);
-        STKHost::get()->sendToServer(&kart, true);
-        // Remove kart screen
-        StateManager::get()->popMenu();
-        TracksScreen::getInstance()->setNetworkTracks();
-        TracksScreen::getInstance()->push();
-    }
-}   // playerConfirm
-
-// ----------------------------------------------------------------------------
-void NetworkKartSelectionScreen::tearDown()
-{
-    KartSelectionScreen::tearDown();
+    // ---- Switch to assign mode
     input_manager->getDeviceManager()->setAssignMode(ASSIGN);
-}   // tearDown
+    // Remove kart screen
+    StateManager::get()->popMenu();
+    TracksScreen::getInstance()->setNetworkTracks();
+    TracksScreen::getInstance()->push();
+
+}   // allPlayersDone
 
 // ----------------------------------------------------------------------------
 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);
     return true; // remove the screen
 }   // onEscapePressed
diff --git a/src/states_screens/network_kart_selection.hpp b/src/states_screens/network_kart_selection.hpp
index 8c01a63e2..3fee9c3a7 100644
--- a/src/states_screens/network_kart_selection.hpp
+++ b/src/states_screens/network_kart_selection.hpp
@@ -27,31 +27,33 @@ class NetworkKartSelectionScreen : public KartSelectionScreen,
                   public GUIEngine::ScreenSingleton<NetworkKartSelectionScreen>
 {
     friend class GUIEngine::ScreenSingleton<NetworkKartSelectionScreen>;
+
 protected:
-    //!< map the id of the kart widgets to race ids
-    std::vector<uint8_t> m_id_mapping;
-
-    NetworkKartSelectionScreen();
-    virtual ~NetworkKartSelectionScreen();
-
-    virtual void playerConfirm(const int playerID) OVERRIDE;
+    // ------------------------------------------------------------------------
+    NetworkKartSelectionScreen() : KartSelectionScreen("karts.stkgui") {}
+    // ------------------------------------------------------------------------
+    ~NetworkKartSelectionScreen() {}
+    // ------------------------------------------------------------------------
+    virtual void allPlayersDone() OVERRIDE;
 
 private:
     std::set<std::string> m_available_karts;
+
+    // ------------------------------------------------------------------------
     virtual bool isIgnored(const std::string& ident) const OVERRIDE
-    {
-        return m_available_karts.find(ident) == m_available_karts.end();
-    }
+           { return m_available_karts.find(ident) == m_available_karts.end(); }
 
 public:
+    // ------------------------------------------------------------------------
     void setAvailableKartsFromServer(const std::set<std::string>& k)
-    {
-        m_available_karts = k;
-    }
+                                                     { m_available_karts = k; }
+    // ------------------------------------------------------------------------
     virtual void init() OVERRIDE;
+    // ------------------------------------------------------------------------
     virtual bool onEscapePressed() OVERRIDE;
-     /** \brief implement callback from parent class GUIEngine::Screen */
-    virtual void tearDown() OVERRIDE;
+    // ------------------------------------------------------------------------
+    virtual bool playerQuit(StateManager::ActivePlayer* player) OVERRIDE
+                                                               { return true; }
 
 };
 
diff --git a/src/states_screens/networking_lobby.cpp b/src/states_screens/networking_lobby.cpp
index 7c293c30a..81984a6fe 100644
--- a/src/states_screens/networking_lobby.cpp
+++ b/src/states_screens/networking_lobby.cpp
@@ -116,36 +116,35 @@ 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);
+    m_state = LS_CONNECTING;
     getWidget("chat")->setVisible(false);
     getWidget("chat")->setActive(false);
     getWidget("send")->setVisible(false);
     getWidget("send")->setActive(false);
 
+    // Connect to server now if we have saved players and not disconnected
+    if (!LobbyProtocol::get<LobbyProtocol>() &&
+        !NetworkConfig::get()->getNetworkPlayers().empty())
+        std::make_shared<ConnectToServer>(m_joined_server)->requestStart();
+
     if (NetworkConfig::get()->getNetworkPlayers().empty())
     {
         m_state = LS_ADD_PLAYERS;
     }
-    else if (NetworkConfig::get()->isClient())
+    else if (NetworkConfig::get()->isClient() &&
+        UserConfigParams::m_lobby_chat)
     {
-        // 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);
-        }
+        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
 
 // ----------------------------------------------------------------------------
@@ -348,18 +347,11 @@ void NetworkingLobby::tearDown()
     if (!NetworkConfig::get()->isClient())
         return;
     input_manager->getDeviceManager()->mapFireToSelect(false);
-    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
diff --git a/src/states_screens/tracks_screen.cpp b/src/states_screens/tracks_screen.cpp
index c6eb6a191..4c21696b1 100644
--- a/src/states_screens/tracks_screen.cpp
+++ b/src/states_screens/tracks_screen.cpp
@@ -161,7 +161,6 @@ void TracksScreen::beforeAddingWidget()
     if (m_bottom_box_height == -1)
         m_bottom_box_height = rect_box->m_h;
 
-    m_votes = getWidget<LabelWidget>("vote-text");
     if (m_network_tracks)
     {
         rect_box->setVisible(true);
@@ -180,7 +179,6 @@ void TracksScreen::beforeAddingWidget()
         m_reversed->m_properties[GUIEngine::PROP_ALIGN] = "center";
         getWidget("all-track")->m_properties[GUIEngine::PROP_WIDTH] = "60%";
         getWidget("vote")->setVisible(true);
-        m_votes->setVisible(true);
         calculateLayout();
     }
     else
@@ -195,9 +193,11 @@ void TracksScreen::beforeAddingWidget()
         getWidget("reverse")->setVisible(false);
         getWidget("all-track")->m_properties[GUIEngine::PROP_WIDTH] = "98%";
         getWidget("vote")->setVisible(false);
-        m_votes->setVisible(false);
         calculateLayout();
     }
+    m_votes = getWidget<LabelWidget>("vote-text");
+    m_votes->setVisible(false);
+
     RibbonWidget* tabs = getWidget<RibbonWidget>("trackgroups");
     tabs->clearAllChildren();
 
@@ -359,11 +359,13 @@ void TracksScreen::setFocusOnTrack(const std::string& trackName)
 // -----------------------------------------------------------------------------
 void TracksScreen::onUpdate(float dt)
 {
+    assert(m_votes);
     if (m_vote_timeout == -1.0f)
     {
+        m_votes->setText(L"", false);
         return;
     }
-    assert(m_votes);
+
     m_votes->setVisible(true);
     int remaining_time = int(m_vote_timeout - float(StkTime::getRealTime()));
     if (remaining_time < 0)