Add team chat for online team game

This commit is contained in:
Benau 2020-05-08 09:21:37 +08:00
parent a776650986
commit 3d74dfea34
7 changed files with 96 additions and 10 deletions

View File

@ -4,9 +4,11 @@
<div x="1%" width="98%" height="fit" layout="horizontal-row"> <div x="1%" width="98%" height="fit" layout="horizontal-row">
<textbox id="chat" proportion="1"/> <textbox id="chat" proportion="1"/>
<spacer width="2%" height="10"/> <spacer width="2%" height="10"/>
<button id="send" width="10%" height="fit" align="center" text=""/> <button id="team" width="7%" height="fit" align="center" text=""/>
<spacer id="team_space" width="1%" height="10"/>
<button id="send" width="7%" height="fit" align="center" text=""/>
<spacer width="1%" height="10"/> <spacer width="1%" height="10"/>
<button id="emoji" width="10%" height="fit" align="center" text=""/> <button id="emoji" width="7%" height="fit" align="center" text=""/>
</div> </div>
<spacer width="20" height="2%" /> <spacer width="20" height="2%" />

View File

@ -1393,7 +1393,7 @@ void ClientLobby::startLiveJoinKartSelection()
} // 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"); text = text.trim().removeChars(L"\n\r");
if (text.size() > 0) if (text.size() > 0)
@ -1410,6 +1410,9 @@ void ClientLobby::sendChat(irr::core::stringw text)
name = player->getName(); name = player->getName();
chat->encodeString16(name + L": " + text, 1000/*max_len*/); chat->encodeString16(name + L": " + text, 1000/*max_len*/);
if (team != KART_TEAM_NONE)
chat->addUInt8(team);
STKHost::get()->sendToServer(chat, true); STKHost::get()->sendToServer(chat, true);
delete chat; delete chat;
} }

View File

@ -169,7 +169,7 @@ public:
bool isSpectator() const bool isSpectator() const
{ return m_spectator && m_state.load() != RACE_FINISHED; } { return m_spectator && m_state.load() != RACE_FINISHED; }
void startLiveJoinKartSelection(); void startLiveJoinKartSelection();
void sendChat(irr::core::stringw text); void sendChat(irr::core::stringw text, KartTeam team);
const std::vector<LobbyPlayer>& getLobbyPlayers() const const std::vector<LobbyPlayer>& getLobbyPlayers() const
{ return m_lobby_players; } { return m_lobby_players; }
bool isServerLiveJoinable() const { return m_server_live_joinable; } bool isServerLiveJoinable() const { return m_server_live_joinable; }

View File

@ -776,14 +776,25 @@ void ServerLobby::handleChat(Event* event)
core::stringw message; core::stringw message;
event->data().decodeString16(&message, 360/*max_len*/); 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) 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(); NetworkString* chat = getNetworkString();
chat->setSynchronous(true); chat->setSynchronous(true);
chat->addUInt8(LE_CHAT).encodeString16(message); chat->addUInt8(LE_CHAT).encodeString16(message);
const bool game_started = m_state.load() != WAITING_FOR_START_GAME; const bool game_started = m_state.load() != WAITING_FOR_START_GAME;
STKHost::get()->sendPacketToAllPeersWith( STKHost::get()->sendPacketToAllPeersWith(
[game_started, sender_in_game](STKPeer* p) [game_started, sender_in_game, target_team](STKPeer* p)
{ {
if (game_started) if (game_started)
{ {
@ -791,6 +802,17 @@ void ServerLobby::handleChat(Event* event)
return false; return false;
if (!p->isWaitingForGame() && sender_in_game) if (!p->isWaitingForGame() && sender_in_game)
return false; 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; return true;
}, chat); }, chat);

View File

@ -26,11 +26,14 @@
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "guiengine/emoji_keyboard.hpp" #include "guiengine/emoji_keyboard.hpp"
#include "guiengine/engine.hpp" #include "guiengine/engine.hpp"
#include "guiengine/layout_manager.hpp"
#include "guiengine/scalable_font.hpp" #include "guiengine/scalable_font.hpp"
#include "guiengine/widgets/CGUIEditBox.hpp" #include "guiengine/widgets/CGUIEditBox.hpp"
#include "guiengine/widgets/icon_button_widget.hpp" #include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp" #include "guiengine/widgets/ribbon_widget.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "karts/controller/controller.hpp"
#include "karts/kart.hpp"
#include "modes/overworld.hpp" #include "modes/overworld.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "network/protocols/client_lobby.hpp" #include "network/protocols/client_lobby.hpp"
@ -58,6 +61,7 @@ RacePausedDialog::RacePausedDialog(const float percentWidth,
const float percentHeight) : const float percentHeight) :
ModalDialog(percentWidth, percentHeight) ModalDialog(percentWidth, percentHeight)
{ {
m_target_team = KART_TEAM_NONE;
m_self_destroy = false; m_self_destroy = false;
m_from_overworld = false; m_from_overworld = false;
@ -201,7 +205,13 @@ GUIEngine::EventPropagation
if (eventSource == "send" && m_text_box) 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; return GUIEngine::EVENT_BLOCK;
} }
else if (eventSource == "emoji" && m_text_box && else if (eventSource == "emoji" && m_text_box &&
@ -385,7 +395,44 @@ void RacePausedDialog::beforeAddingWidgets()
choice_ribbon->setItemVisible(index, false); choice_ribbon->setItemVisible(index, false);
} }
if (NetworkConfig::get()->isNetworking()) 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<TextBoxWidget>("chat"); m_text_box = getWidget<TextBoxWidget>("chat");
}
else else
m_text_box = NULL; m_text_box = NULL;
@ -420,7 +467,7 @@ void RacePausedDialog::init()
} // init } // init
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool RacePausedDialog::onEnterPressed(const irr::core::stringw& text) void RacePausedDialog::handleChat(const irr::core::stringw& text)
{ {
if (auto cl = LobbyProtocol::get<ClientLobby>()) if (auto cl = LobbyProtocol::get<ClientLobby>())
{ {
@ -432,13 +479,22 @@ bool RacePausedDialog::onEnterPressed(const irr::core::stringw& text)
cl->handleClientCommand(cmd.erase(0, 1)); cl->handleClientCommand(cmd.erase(0, 1));
} }
else else
cl->sendChat(text); cl->sendChat(text, m_target_team);
} }
} }
m_self_destroy = true; 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; return true;
} // onEnterPressed } // onEnterPressed
// ----------------------------------------------------------------------------
void RacePausedDialog::updateTouchDeviceIcon() void RacePausedDialog::updateTouchDeviceIcon()
{ {
GUIEngine::RibbonWidget* backbtn_ribbon = GUIEngine::RibbonWidget* backbtn_ribbon =
@ -469,4 +525,4 @@ void RacePausedDialog::updateTouchDeviceIcon()
default: default:
break; break;
} }
} } // updateTouchDeviceIcon

View File

@ -27,6 +27,7 @@ namespace GUIEngine
class RibbonWidget; class RibbonWidget;
class TextBoxWidget; class TextBoxWidget;
} }
enum KartTeam : int8_t;
/** /**
* \brief Dialog shown when the race is paused * \brief Dialog shown when the race is paused
@ -36,6 +37,7 @@ class RacePausedDialog : public GUIEngine::ModalDialog,
public GUIEngine::ITextBoxWidgetListener public GUIEngine::ITextBoxWidgetListener
{ {
private: private:
KartTeam m_target_team;
bool m_self_destroy; bool m_self_destroy;
bool m_from_overworld; bool m_from_overworld;
int m_touch_controls; int m_touch_controls;
@ -43,6 +45,7 @@ private:
GUIEngine::TextBoxWidget* m_text_box; GUIEngine::TextBoxWidget* m_text_box;
virtual void onTextUpdated() OVERRIDE {} virtual void onTextUpdated() OVERRIDE {}
void handleChat(const irr::core::stringw& text);
virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE; virtual bool onEnterPressed(const irr::core::stringw& text) OVERRIDE;
void updateTouchDeviceIcon(); void updateTouchDeviceIcon();

View File

@ -609,7 +609,7 @@ bool NetworkingLobby::onEnterPressed(const irr::core::stringw& text)
cl->handleClientCommand(cmd.erase(0, 1)); cl->handleClientCommand(cmd.erase(0, 1));
} }
else else
cl->sendChat(text); cl->sendChat(text, KART_TEAM_NONE);
} }
} }
return true; return true;