Implemented cCompositeChat.
This allows plugins to send composite chat messages, containing URLs, commands to run and cmdline suggestions. Fixes #678.
This commit is contained in:
@@ -8,6 +8,7 @@ Implements the 1.7.x protocol classes:
|
||||
*/
|
||||
|
||||
#include "Globals.h"
|
||||
#include "json/json.h"
|
||||
#include "Protocol17x.h"
|
||||
#include "ChunkDataSerializer.h"
|
||||
#include "../ClientHandle.h"
|
||||
@@ -25,6 +26,7 @@ Implements the 1.7.x protocol classes:
|
||||
#include "../Mobs/IncludeAllMonsters.h"
|
||||
#include "../UI/Window.h"
|
||||
#include "../BlockEntities/CommandBlockEntity.h"
|
||||
#include "../CompositeChat.h"
|
||||
|
||||
|
||||
|
||||
@@ -200,6 +202,78 @@ void cProtocol172::SendChat(const AString & a_Message)
|
||||
|
||||
|
||||
|
||||
void cProtocol172::SendChat(const cCompositeChat & a_Message)
|
||||
{
|
||||
// Compose the complete Json string to send:
|
||||
Json::Value msg;
|
||||
msg["text"] = ""; // The client crashes without this
|
||||
const cCompositeChat::cParts & Parts = a_Message.GetParts();
|
||||
for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr)
|
||||
{
|
||||
Json::Value Part;
|
||||
switch ((*itr)->m_PartType)
|
||||
{
|
||||
case cCompositeChat::ptText:
|
||||
{
|
||||
Part["text"] = (*itr)->m_Text;
|
||||
AddChatPartStyle(Part, (*itr)->m_Style);
|
||||
break;
|
||||
}
|
||||
|
||||
case cCompositeChat::ptClientTranslated:
|
||||
{
|
||||
const cCompositeChat::cClientTranslatedPart & p = (const cCompositeChat::cClientTranslatedPart &)**itr;
|
||||
Part["translate"] = p.m_Text;
|
||||
Json::Value With;
|
||||
for (AStringVector::const_iterator itrW = p.m_Parameters.begin(), endW = p.m_Parameters.end(); itrW != endW; ++itr)
|
||||
{
|
||||
With.append(*itrW);
|
||||
}
|
||||
if (!p.m_Parameters.empty())
|
||||
{
|
||||
Part["with"] = With;
|
||||
}
|
||||
AddChatPartStyle(Part, p.m_Style);
|
||||
break;
|
||||
}
|
||||
|
||||
case cCompositeChat::ptUrl:
|
||||
{
|
||||
const cCompositeChat::cUrlPart & p = (const cCompositeChat::cUrlPart &)**itr;
|
||||
Part["text"] = p.m_Text;
|
||||
Json::Value Url;
|
||||
Url["action"] = "open_url";
|
||||
Url["value"] = p.m_Url;
|
||||
Part["clickEvent"] = Url;
|
||||
AddChatPartStyle(Part, p.m_Style);
|
||||
break;
|
||||
}
|
||||
|
||||
case cCompositeChat::ptSuggestCommand:
|
||||
case cCompositeChat::ptRunCommand:
|
||||
{
|
||||
const cCompositeChat::cCommandPart & p = (const cCompositeChat::cCommandPart &)**itr;
|
||||
Part["text"] = p.m_Text;
|
||||
Json::Value Cmd;
|
||||
Cmd["action"] = (p.m_PartType == cCompositeChat::ptRunCommand) ? "run_command" : "suggest_command";
|
||||
Cmd["value"] = p.m_Command;
|
||||
Part["clickEvent"] = Cmd;
|
||||
AddChatPartStyle(Part, p.m_Style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg["extra"].append(Part);
|
||||
} // for itr - Parts[]
|
||||
|
||||
// Send the message to the client:
|
||||
cPacketizer Pkt(*this, 0x02);
|
||||
Pkt.WriteString(msg.toStyledString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
|
||||
{
|
||||
// Serialize first, before creating the Packetizer (the packetizer locks a CS)
|
||||
@@ -1979,6 +2053,85 @@ void cProtocol172::StartEncryption(const Byte * a_Key)
|
||||
|
||||
|
||||
|
||||
void cProtocol172::AddChatPartStyle(Json::Value & a_Value, const AString & a_PartStyle)
|
||||
{
|
||||
size_t len = a_PartStyle.length();
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
switch (a_PartStyle[i])
|
||||
{
|
||||
case 'b':
|
||||
{
|
||||
// bold
|
||||
a_Value["bold"] = Json::Value(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
// italic
|
||||
a_Value["italic"] = Json::Value(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'u':
|
||||
{
|
||||
// Underlined
|
||||
a_Value["underlined"] = Json::Value(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
// strikethrough
|
||||
a_Value["strikethrough"] = Json::Value(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
{
|
||||
// obfuscated
|
||||
a_Value["obfuscated"] = Json::Value(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case '@':
|
||||
{
|
||||
// Color, specified by the next char:
|
||||
i++;
|
||||
if (i >= len)
|
||||
{
|
||||
// String too short, didn't contain a color
|
||||
break;
|
||||
}
|
||||
switch (a_PartStyle[i])
|
||||
{
|
||||
case '0': a_Value["color"] = Json::Value("black"); break;
|
||||
case '1': a_Value["color"] = Json::Value("dark_blue"); break;
|
||||
case '2': a_Value["color"] = Json::Value("dark_green"); break;
|
||||
case '3': a_Value["color"] = Json::Value("dark_aqua"); break;
|
||||
case '4': a_Value["color"] = Json::Value("dark_red"); break;
|
||||
case '5': a_Value["color"] = Json::Value("dark_purple"); break;
|
||||
case '6': a_Value["color"] = Json::Value("gold"); break;
|
||||
case '7': a_Value["color"] = Json::Value("gray"); break;
|
||||
case '8': a_Value["color"] = Json::Value("dark_gray"); break;
|
||||
case '9': a_Value["color"] = Json::Value("blue"); break;
|
||||
case 'a': a_Value["color"] = Json::Value("green"); break;
|
||||
case 'b': a_Value["color"] = Json::Value("aqua"); break;
|
||||
case 'c': a_Value["color"] = Json::Value("red"); break;
|
||||
case 'd': a_Value["color"] = Json::Value("light_purple"); break;
|
||||
case 'e': a_Value["color"] = Json::Value("yellow"); break;
|
||||
case 'f': a_Value["color"] = Json::Value("white"); break;
|
||||
} // switch (color)
|
||||
} // case '@'
|
||||
} // switch (Style[i])
|
||||
} // for i - a_PartStyle[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cProtocol172::cPacketizer:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user