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: