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">
<textbox id="chat" proportion="1"/>
<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"/>
<button id="emoji" width="10%" height="fit" align="center" text=""/>
<button id="emoji" width="7%" height="fit" align="center" text=""/>
</div>
<spacer width="20" height="2%" />

View File

@ -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;
}

View File

@ -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<LobbyPlayer>& getLobbyPlayers() const
{ return m_lobby_players; }
bool isServerLiveJoinable() const { return m_server_live_joinable; }

View File

@ -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);

View File

@ -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<TextBoxWidget>("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<ClientLobby>())
{
@ -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

View File

@ -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();

View File

@ -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;