diff --git a/data/gui/dialogs/network_ingame_dialog.stkgui b/data/gui/dialogs/network_ingame_dialog.stkgui
new file mode 100644
index 000000000..958ea2a10
--- /dev/null
+++ b/data/gui/dialogs/network_ingame_dialog.stkgui
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp
index c131d4189..20c152e86 100644
--- a/src/network/protocols/client_lobby.cpp
+++ b/src/network/protocols/client_lobby.cpp
@@ -772,7 +772,10 @@ void ClientLobby::handleChat(Event* event)
Log::info("ClientLobby", "%s", StringUtils::wideToUtf8(message).c_str());
if (message.size() > 0)
{
- NetworkingLobby::getInstance()->addMoreServerInfo(message);
+ if (GUIEngine::getCurrentScreen() == NetworkingLobby::getInstance())
+ NetworkingLobby::getInstance()->addMoreServerInfo(message);
+ else
+ MessageQueue::add(MessageQueue::MT_GENERIC, message);
}
} // handleChat
@@ -1154,3 +1157,27 @@ void ClientLobby::startLiveJoinKartSelection()
->setAvailableKartsFromServer(karts);
NetworkKartSelectionScreen::getInstance()->push();
} // startLiveJoinKartSelection
+
+
+// ----------------------------------------------------------------------------
+void ClientLobby::sendChat(irr::core::stringw text)
+{
+ text = text.trim().removeChars(L"\n\r");
+ if (text.size() > 0)
+ {
+ NetworkString* chat = getNetworkString();
+ chat->addUInt8(LobbyProtocol::LE_CHAT);
+
+ core::stringw name;
+ PlayerProfile* player = PlayerManager::getCurrentPlayer();
+ if (PlayerManager::getCurrentOnlineState() ==
+ PlayerProfile::OS_SIGNED_IN)
+ name = PlayerManager::getCurrentOnlineUserName();
+ else
+ name = player->getName();
+ chat->encodeString16(name + L": " + text);
+
+ STKHost::get()->sendToServer(chat, true);
+ delete chat;
+ }
+} // sendChat
diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp
index b030b6f03..caf1ef1f2 100644
--- a/src/network/protocols/client_lobby.hpp
+++ b/src/network/protocols/client_lobby.hpp
@@ -130,6 +130,7 @@ public:
void setSpectator(bool val) { m_spectator = val; }
bool isSpectator() const { return m_spectator; }
void startLiveJoinKartSelection();
+ void sendChat(irr::core::stringw text);
};
#endif // CLIENT_LOBBY_HPP
diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp
index 82a7b73eb..cfe06be7d 100644
--- a/src/network/protocols/server_lobby.cpp
+++ b/src/network/protocols/server_lobby.cpp
@@ -316,6 +316,7 @@ void ServerLobby::handleChat(Event* event)
{
if (!checkDataSize(event, 1)) return;
+ const bool sender_in_game = event->getPeer()->isWaitingForGame();
core::stringw message;
event->data().decodeString16(&message);
if (message.size() > 0)
@@ -323,17 +324,19 @@ void ServerLobby::handleChat(Event* event)
NetworkString* chat = getNetworkString();
chat->setSynchronous(true);
chat->addUInt8(LE_CHAT).encodeString16(message);
- // After game is started, only send to waiting player
const bool game_started = m_state.load() != WAITING_FOR_START_GAME;
- STKHost::get()->sendPacketToAllPeersWith([game_started]
- (STKPeer* p)
+ STKHost::get()->sendPacketToAllPeersWith(
+ [game_started, sender_in_game](STKPeer* p)
{
if (!p->isValidated())
return false;
- if (!game_started)
- return true;
- if (!p->isWaitingForGame() && game_started)
- return false;
+ if (game_started)
+ {
+ if (p->isWaitingForGame() && !sender_in_game)
+ return false;
+ if (!p->isWaitingForGame() && sender_in_game)
+ return false;
+ }
return true;
}, chat);
delete chat;
diff --git a/src/states_screens/dialogs/race_paused_dialog.cpp b/src/states_screens/dialogs/race_paused_dialog.cpp
index 3aec57c2a..4603de4c1 100644
--- a/src/states_screens/dialogs/race_paused_dialog.cpp
+++ b/src/states_screens/dialogs/race_paused_dialog.cpp
@@ -21,6 +21,7 @@
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
+#include "config/user_config.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
@@ -28,7 +29,7 @@
#include "io/file_manager.hpp"
#include "modes/overworld.hpp"
#include "modes/world.hpp"
-#include "network/protocols/lobby_protocol.hpp"
+#include "network/protocols/client_lobby.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
#include "network/stk_host.hpp"
@@ -51,14 +52,19 @@ RacePausedDialog::RacePausedDialog(const float percentWidth,
const float percentHeight) :
ModalDialog(percentWidth, percentHeight)
{
+ m_self_destroy = false;
if (dynamic_cast(World::getWorld()) != NULL)
{
loadFromFile("overworld_dialog.stkgui");
}
- else
+ else if (!NetworkConfig::get()->isNetworking())
{
loadFromFile("race_paused_dialog.stkgui");
}
+ else
+ {
+ loadFromFile("network_ingame_dialog.stkgui");
+ }
GUIEngine::RibbonWidget* back_btn = getWidget("backbtnribbon");
back_btn->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
@@ -67,6 +73,20 @@ RacePausedDialog::RacePausedDialog(const float percentWidth,
{
music_manager->pauseMusic();
SFXManager::get()->pauseAll();
+ m_text_box->clearListeners();
+ if (UserConfigParams::m_lobby_chat)
+ {
+ m_text_box->setActive(true);
+ getWidget("send")->setVisible(true);
+ m_text_box->addListener(this);
+ }
+ else
+ {
+ m_text_box->setActive(false);
+ m_text_box->setText(
+ _("Chat is disabled, enable in options menu."));
+ getWidget("send")->setVisible(false);
+ }
}
else
{
@@ -137,7 +157,12 @@ GUIEngine::EventPropagation
GUIEngine::RibbonWidget* choice_ribbon =
getWidget("choiceribbon");
- if (eventSource == "backbtnribbon")
+ if (eventSource == "send" && m_text_box)
+ {
+ onEnterPressed(m_text_box->getText());
+ return GUIEngine::EVENT_BLOCK;
+ }
+ else if (eventSource == "backbtnribbon")
{
// unpausing is done in the destructor so nothing more to do here
ModalDialog::dismiss();
@@ -263,14 +288,16 @@ void RacePausedDialog::beforeAddingWidgets()
choice_ribbon->setItemVisible(index, false);
}
if (NetworkConfig::get()->isNetworking())
- {
- IconButtonWidget* new_race = dynamic_cast
- (choice_ribbon->findWidgetNamed("newrace"));
- if (new_race)
- {
- //I18N: show in race paused dialog in network to allow user to go
- //back to lobby to end spectating (for example)
- new_race->setText(_("Back to lobby"));
- }
- }
+ m_text_box = getWidget("chat");
+ else
+ m_text_box = NULL;
} // beforeAddingWidgets
+
+// ----------------------------------------------------------------------------
+bool RacePausedDialog::onEnterPressed(const irr::core::stringw& text)
+{
+ if (auto cl = LobbyProtocol::get())
+ cl->sendChat(text);
+ m_self_destroy = true;
+ return true;
+} // onEnterPressed
diff --git a/src/states_screens/dialogs/race_paused_dialog.hpp b/src/states_screens/dialogs/race_paused_dialog.hpp
index d9a6476d1..c3dc5e40a 100644
--- a/src/states_screens/dialogs/race_paused_dialog.hpp
+++ b/src/states_screens/dialogs/race_paused_dialog.hpp
@@ -19,20 +19,30 @@
#define HEADER_RACE_PAUSED_DIALOG_HPP
#include "guiengine/modaldialog.hpp"
+#include "guiengine/widgets/text_box_widget.hpp"
#include "utils/cpp2011.hpp"
namespace GUIEngine
{
class RibbonWidget;
+ class TextBoxWidget;
}
/**
* \brief Dialog shown when the race is paused
* \ingroup states_screens
*/
-class RacePausedDialog : public GUIEngine::ModalDialog
+class RacePausedDialog : public GUIEngine::ModalDialog,
+ public GUIEngine::ITextBoxWidgetListener
{
-
+private:
+ bool m_self_destroy;
+
+ GUIEngine::TextBoxWidget* m_text_box;
+
+ virtual void onTextUpdated() OVERRIDE {}
+ virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE;
+
protected:
virtual void loadedFromFile() OVERRIDE;
@@ -46,6 +56,16 @@ public:
GUIEngine::EventPropagation processEvent(const std::string& eventSource)
OVERRIDE;
virtual void beforeAddingWidgets() OVERRIDE;
+ // ------------------------------------------------------------------------
+ virtual void onUpdate(float dt) OVERRIDE
+ {
+ // It's unsafe to delete from inside the event handler so we do it here
+ if (m_self_destroy)
+ {
+ ModalDialog::dismiss();
+ return;
+ }
+ }
};
#endif
diff --git a/src/states_screens/online/networking_lobby.cpp b/src/states_screens/online/networking_lobby.cpp
index 47f30538f..2f9dd453f 100644
--- a/src/states_screens/online/networking_lobby.cpp
+++ b/src/states_screens/online/networking_lobby.cpp
@@ -515,26 +515,12 @@ void NetworkingLobby::updatePlayerPings()
} // updatePlayerPings
// ----------------------------------------------------------------------------
-void NetworkingLobby::sendChat(irr::core::stringw text)
+bool NetworkingLobby::onEnterPressed(const irr::core::stringw& text)
{
- text = text.trim().removeChars(L"\n\r");
- if (text.size() > 0)
- {
- NetworkString chat(PROTOCOL_LOBBY_ROOM);
- chat.addUInt8(LobbyProtocol::LE_CHAT);
-
- core::stringw name;
- PlayerProfile* player = PlayerManager::getCurrentPlayer();
- if (PlayerManager::getCurrentOnlineState() ==
- PlayerProfile::OS_SIGNED_IN)
- name = PlayerManager::getCurrentOnlineUserName();
- else
- name = player->getName();
- chat.encodeString16(name + L": " + text);
-
- STKHost::get()->sendToServer(&chat, true);
- }
-} // sendChat
+ if (auto cl = LobbyProtocol::get())
+ cl->sendChat(text);
+ return true;
+} // onEnterPressed
// ----------------------------------------------------------------------------
void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
@@ -563,7 +549,8 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
} // click on a user
else if (name == m_send_button->m_properties[PROP_ID])
{
- sendChat(m_chat_box->getText());
+ if (auto cl = LobbyProtocol::get())
+ cl->sendChat(m_chat_box->getText());
m_chat_box->setText("");
} // send chat message
else if (name == m_start_button->m_properties[PROP_ID])
diff --git a/src/states_screens/online/networking_lobby.hpp b/src/states_screens/online/networking_lobby.hpp
index e67b2ee75..35dced10c 100644
--- a/src/states_screens/online/networking_lobby.hpp
+++ b/src/states_screens/online/networking_lobby.hpp
@@ -102,13 +102,7 @@ private:
virtual void unloaded() OVERRIDE;
virtual void onTextUpdated() OVERRIDE {}
- virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE
- {
- sendChat(text);
- return true;
- }
-
- void sendChat(irr::core::stringw text);
+ virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE;
void updatePlayerPings();
public: