From 3d74dfea341b238c1e9968a9128d68b4f07abb52 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 8 May 2020 09:21:37 +0800 Subject: [PATCH] Add team chat for online team game --- .../online/network_ingame_dialog.stkgui | 6 +- src/network/protocols/client_lobby.cpp | 5 +- src/network/protocols/client_lobby.hpp | 2 +- src/network/protocols/server_lobby.cpp | 24 ++++++- .../dialogs/race_paused_dialog.cpp | 64 +++++++++++++++++-- .../dialogs/race_paused_dialog.hpp | 3 + .../online/networking_lobby.cpp | 2 +- 7 files changed, 96 insertions(+), 10 deletions(-) diff --git a/data/gui/dialogs/online/network_ingame_dialog.stkgui b/data/gui/dialogs/online/network_ingame_dialog.stkgui index 749ca492a..14c8daa43 100644 --- a/data/gui/dialogs/online/network_ingame_dialog.stkgui +++ b/data/gui/dialogs/online/network_ingame_dialog.stkgui @@ -4,9 +4,11 @@
-
diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index fa45d4f34..0dcf84eee 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -1393,7 +1393,7 @@ void ClientLobby::startLiveJoinKartSelection() } // startLiveJoinKartSelection // ---------------------------------------------------------------------------- -void ClientLobby::sendChat(irr::core::stringw text) +void ClientLobby::sendChat(irr::core::stringw text, KartTeam team) { text = text.trim().removeChars(L"\n\r"); if (text.size() > 0) @@ -1410,6 +1410,9 @@ void ClientLobby::sendChat(irr::core::stringw text) name = player->getName(); chat->encodeString16(name + L": " + text, 1000/*max_len*/); + if (team != KART_TEAM_NONE) + chat->addUInt8(team); + STKHost::get()->sendToServer(chat, true); delete chat; } diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp index 32374a9fd..edcab128e 100644 --- a/src/network/protocols/client_lobby.hpp +++ b/src/network/protocols/client_lobby.hpp @@ -169,7 +169,7 @@ public: bool isSpectator() const { return m_spectator && m_state.load() != RACE_FINISHED; } void startLiveJoinKartSelection(); - void sendChat(irr::core::stringw text); + void sendChat(irr::core::stringw text, KartTeam team); const std::vector& getLobbyPlayers() const { return m_lobby_players; } bool isServerLiveJoinable() const { return m_server_live_joinable; } diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 3ad781eae..0b632eca0 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -776,14 +776,25 @@ void ServerLobby::handleChat(Event* event) core::stringw message; event->data().decodeString16(&message, 360/*max_len*/); + + KartTeam target_team = KART_TEAM_NONE; + if (event->data().size() > 0) + target_team = (KartTeam)event->data().getUInt8(); + if (message.size() > 0) { + // Red or blue square emoji + if (target_team == KART_TEAM_RED) + message = StringUtils::utf32ToWide({0x1f7e5, 0x20}) + message; + else if (target_team == KART_TEAM_BLUE) + message = StringUtils::utf32ToWide({0x1f7e6, 0x20}) + message; + NetworkString* chat = getNetworkString(); chat->setSynchronous(true); chat->addUInt8(LE_CHAT).encodeString16(message); const bool game_started = m_state.load() != WAITING_FOR_START_GAME; STKHost::get()->sendPacketToAllPeersWith( - [game_started, sender_in_game](STKPeer* p) + [game_started, sender_in_game, target_team](STKPeer* p) { if (game_started) { @@ -791,6 +802,17 @@ void ServerLobby::handleChat(Event* event) return false; if (!p->isWaitingForGame() && sender_in_game) return false; + if (target_team != KART_TEAM_NONE) + { + if (p->isSpectator()) + return false; + for (auto& player : p->getPlayerProfiles()) + { + if (player->getTeam() == target_team) + return true; + } + return false; + } } return true; }, chat); diff --git a/src/states_screens/dialogs/race_paused_dialog.cpp b/src/states_screens/dialogs/race_paused_dialog.cpp index 8bd9c3a7b..699c807fd 100644 --- a/src/states_screens/dialogs/race_paused_dialog.cpp +++ b/src/states_screens/dialogs/race_paused_dialog.cpp @@ -26,11 +26,14 @@ #include "graphics/irr_driver.hpp" #include "guiengine/emoji_keyboard.hpp" #include "guiengine/engine.hpp" +#include "guiengine/layout_manager.hpp" #include "guiengine/scalable_font.hpp" #include "guiengine/widgets/CGUIEditBox.hpp" #include "guiengine/widgets/icon_button_widget.hpp" #include "guiengine/widgets/ribbon_widget.hpp" #include "io/file_manager.hpp" +#include "karts/controller/controller.hpp" +#include "karts/kart.hpp" #include "modes/overworld.hpp" #include "modes/world.hpp" #include "network/protocols/client_lobby.hpp" @@ -58,6 +61,7 @@ RacePausedDialog::RacePausedDialog(const float percentWidth, const float percentHeight) : ModalDialog(percentWidth, percentHeight) { + m_target_team = KART_TEAM_NONE; m_self_destroy = false; m_from_overworld = false; @@ -201,7 +205,13 @@ GUIEngine::EventPropagation if (eventSource == "send" && m_text_box) { - onEnterPressed(m_text_box->getText()); + m_target_team = KART_TEAM_NONE; + handleChat(m_text_box->getText()); + return GUIEngine::EVENT_BLOCK; + } + if (eventSource == "team" && m_text_box) + { + handleChat(m_text_box->getText()); return GUIEngine::EVENT_BLOCK; } else if (eventSource == "emoji" && m_text_box && @@ -385,7 +395,44 @@ void RacePausedDialog::beforeAddingWidgets() choice_ribbon->setItemVisible(index, false); } if (NetworkConfig::get()->isNetworking()) + { + int id = 0; + for (auto& kart : World::getWorld()->getKarts()) + { + if (!World::getWorld()->hasTeam()) + break; + // Handle only 1st local player even splitscreen + if (kart->getController()->isLocalPlayerController()) + { + m_target_team = + RaceManager::get()->getKartInfo(id).getKartTeam(); + break; + } + id++; + } + if (m_target_team == KART_TEAM_RED) + { + getWidget("team")->setVisible(true); + getWidget("team")->m_properties[GUIEngine::PROP_WIDTH] = "7%"; + getWidget("team_space")->m_properties[GUIEngine::PROP_WIDTH] = "1%"; + getWidget("team")->setText(StringUtils::utf32ToWide({0x1f7e5})); + } + else if (m_target_team == KART_TEAM_BLUE) + { + getWidget("team")->setVisible(true); + getWidget("team")->m_properties[GUIEngine::PROP_WIDTH] = "7%"; + getWidget("team_space")->m_properties[GUIEngine::PROP_WIDTH] = "1%"; + getWidget("team")->setText(StringUtils::utf32ToWide({0x1f7e6})); + } + else + { + getWidget("team")->m_properties[GUIEngine::PROP_WIDTH] = "0%"; + getWidget("team_space")->m_properties[GUIEngine::PROP_WIDTH] = "0%"; + getWidget("team")->setVisible(false); + } + LayoutManager::calculateLayout(m_widgets, this); m_text_box = getWidget("chat"); + } else m_text_box = NULL; @@ -420,7 +467,7 @@ void RacePausedDialog::init() } // init // ---------------------------------------------------------------------------- -bool RacePausedDialog::onEnterPressed(const irr::core::stringw& text) +void RacePausedDialog::handleChat(const irr::core::stringw& text) { if (auto cl = LobbyProtocol::get()) { @@ -432,13 +479,22 @@ bool RacePausedDialog::onEnterPressed(const irr::core::stringw& text) cl->handleClientCommand(cmd.erase(0, 1)); } else - cl->sendChat(text); + cl->sendChat(text, m_target_team); } } m_self_destroy = true; +} // onEnterPressed + +// ---------------------------------------------------------------------------- +bool RacePausedDialog::onEnterPressed(const irr::core::stringw& text) +{ + // Assume enter for non team chat + m_target_team = KART_TEAM_NONE; + handleChat(text); return true; } // onEnterPressed +// ---------------------------------------------------------------------------- void RacePausedDialog::updateTouchDeviceIcon() { GUIEngine::RibbonWidget* backbtn_ribbon = @@ -469,4 +525,4 @@ void RacePausedDialog::updateTouchDeviceIcon() default: break; } -} +} // updateTouchDeviceIcon diff --git a/src/states_screens/dialogs/race_paused_dialog.hpp b/src/states_screens/dialogs/race_paused_dialog.hpp index 8b5e0547f..aa5efbe44 100644 --- a/src/states_screens/dialogs/race_paused_dialog.hpp +++ b/src/states_screens/dialogs/race_paused_dialog.hpp @@ -27,6 +27,7 @@ namespace GUIEngine class RibbonWidget; class TextBoxWidget; } +enum KartTeam : int8_t; /** * \brief Dialog shown when the race is paused @@ -36,6 +37,7 @@ class RacePausedDialog : public GUIEngine::ModalDialog, public GUIEngine::ITextBoxWidgetListener { private: + KartTeam m_target_team; bool m_self_destroy; bool m_from_overworld; int m_touch_controls; @@ -43,6 +45,7 @@ private: GUIEngine::TextBoxWidget* m_text_box; virtual void onTextUpdated() OVERRIDE {} + void handleChat(const irr::core::stringw& text); virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE; void updateTouchDeviceIcon(); diff --git a/src/states_screens/online/networking_lobby.cpp b/src/states_screens/online/networking_lobby.cpp index 3dd00df26..3e398e06e 100644 --- a/src/states_screens/online/networking_lobby.cpp +++ b/src/states_screens/online/networking_lobby.cpp @@ -609,7 +609,7 @@ bool NetworkingLobby::onEnterPressed(const irr::core::stringw& text) cl->handleClientCommand(cmd.erase(0, 1)); } else - cl->sendChat(text); + cl->sendChat(text, KART_TEAM_NONE); } } return true;