Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Minecraft.Client/ChatScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
cursorIndex--;
return;
}
if (isAllowedChatChar(ch) && static_cast<int>(message.length()) < SharedConstants::maxChatLength)
if (isAllowedChatChar(ch) && static_cast<int>(message.length()) < SharedConstants::maxVisibleLength)
{
message.insert(cursorIndex, 1, ch);
cursorIndex++;
Expand Down
31 changes: 26 additions & 5 deletions Minecraft.Client/ClientConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "..\Minecraft.World\DurangoStats.h"
#include "..\Minecraft.World\GenericStats.h"
#endif
#include <regex>

ClientConnection::ClientConnection(Minecraft *minecraft, const wstring& ip, int port)
{
Expand Down Expand Up @@ -1546,17 +1547,35 @@ void ClientConnection::handleChat(shared_ptr<ChatPacket> packet)
bool replaceEntitySource = false;
bool replaceItem = false;

static std::wregex IDS_Pattern(LR"(\{\*IDS_(\d+)\*\})"); //maybe theres a better way to do translateable IDS

int stringArgsSize = packet->m_stringArgs.size();

wstring playerDisplayName = L"";
wstring sourceDisplayName = L"";

// On platforms other than Xbox One this just sets display name to gamertag
if (packet->m_stringArgs.size() >= 1) playerDisplayName = GetDisplayNameByGamertag(packet->m_stringArgs[0]);
if (packet->m_stringArgs.size() >= 2) sourceDisplayName = GetDisplayNameByGamertag(packet->m_stringArgs[1]);
if (stringArgsSize >= 1) playerDisplayName = GetDisplayNameByGamertag(packet->m_stringArgs[0]);
if (stringArgsSize >= 2) sourceDisplayName = GetDisplayNameByGamertag(packet->m_stringArgs[1]);

switch(packet->m_messageType)
{
case ChatPacket::e_ChatCustom:
message = (packet->m_stringArgs.size() >= 1) ? packet->m_stringArgs[0] : L"";
case ChatPacket::e_ChatActionBar:
if (stringArgsSize >= 1) {
message = packet->m_stringArgs[0];

std::wsmatch match;
while (std::regex_search(message, match, IDS_Pattern)) {
message = replaceAll(message, match[0], app.GetString(std::stoi(match[1].str())));
}

message = app.EscapeHTMLString(message); //do this to enforce escaped string
message = app.FormatChatMessage(message); //this needs to be last cause it converts colors to html colors that would have been escaped
} else {
message = L"empty message";
}
displayOnGui = (packet->m_messageType == ChatPacket::e_ChatCustom);
break;
case ChatPacket::e_ChatBedOccupied:
message = app.GetString(IDS_TILE_BED_OCCUPIED);
Expand Down Expand Up @@ -1906,7 +1925,7 @@ void ClientConnection::handleChat(shared_ptr<ChatPacket> packet)

if(replacePlayer)
{
message = replaceAll(message,L"{*PLAYER*}",playerDisplayName);
message = replaceAll(message,L"{*PLAYER*}", playerDisplayName);
}

if(replaceEntitySource)
Expand Down Expand Up @@ -1941,7 +1960,9 @@ void ClientConnection::handleChat(shared_ptr<ChatPacket> packet)
// flag that a message is a death message
bool bIsDeathMessage = (packet->m_messageType>=ChatPacket::e_ChatDeathInFire) && (packet->m_messageType<=ChatPacket::e_ChatDeathIndirectMagicItem);

if( displayOnGui ) minecraft->gui->addMessage(message,m_userIndex, bIsDeathMessage);
if( displayOnGui ) minecraft->gui->addMessage(message, m_userIndex, bIsDeathMessage);

if (!displayOnGui && !message.empty()) minecraft->gui->setActionBarMessage(message);
}

void ClientConnection::handleAnimate(shared_ptr<AnimatePacket> packet)
Expand Down
81 changes: 81 additions & 0 deletions Minecraft.Client/Common/Consoles_App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6595,6 +6595,87 @@ wstring CMinecraftApp::FormatHTMLString(int iPad, const wstring &desc, int shado
return text;
}

//found list of html escapes at https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html
wstring CMinecraftApp::EscapeHTMLString(const wstring& desc)
{
static std::unordered_map<wchar_t, wchar_t*> replacementMap = {
{L'&', L"&amp;"},
{L'<', L"&lt;"},
{L'>', L"&gt;"},
{L'\"', L"&quot;"},
{L'\'', L"&#39;"},
};

wstring finalString = L"";
for (int i = 0; i < desc.size(); i++) {
wchar_t _char = desc[i];
auto it = replacementMap.find(_char);

if (it != replacementMap.end()) finalString += it->second;
else finalString += _char;
}

return finalString;
}

wstring CMinecraftApp::FormatChatMessage(const wstring& desc, bool applyColor)
{
static std::wstring_view colorFormatString = L"<font color=\"#%08x\" shadowcolor=\"#%08x\">";

wstring results = desc;
wchar_t replacements[64];

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_0), 0xFFFFFFFF);
results = replaceAll(results, L"§0", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_1), 0xFFFFFFFF);
results = replaceAll(results, L"§1", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_2), 0xFFFFFFFF);
results = replaceAll(results, L"§2", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_3), 0xFFFFFFFF);
results = replaceAll(results, L"§3", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_4), 0xFFFFFFFF);
results = replaceAll(results, L"§4", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_5), 0xFFFFFFFF);
results = replaceAll(results, L"§5", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_6), 0xFFFFFFFF);
results = replaceAll(results, L"§6", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_7), 0xFFFFFFFF);
results = replaceAll(results, L"§7", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_8), 0xFFFFFFFF);
results = replaceAll(results, L"§8", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_9), 0xFFFFFFFF);
results = replaceAll(results, L"§9", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_a), 0xFFFFFFFF);
results = replaceAll(results, L"§a", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_b), 0xFFFFFFFF);
results = replaceAll(results, L"§b", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_c), 0xFFFFFFFF);
results = replaceAll(results, L"§c", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_d), 0xFFFFFFFF);
results = replaceAll(results, L"§d", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_e), 0xFFFFFFFF);
results = replaceAll(results, L"§e", replacements);

swprintf(replacements, 64, (applyColor ? colorFormatString.data() : L""), GetHTMLColour(eHTMLColor_f), 0xFFFFFFFF);
results = replaceAll(results, L"§f", replacements);

return results;
}

wstring CMinecraftApp::GetActionReplacement(int iPad, unsigned char ucAction)
{
unsigned int input = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal(iPad) ,ucAction);
Expand Down
4 changes: 3 additions & 1 deletion Minecraft.Client/Common/Consoles_App.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,9 @@ class CMinecraftApp
int GetHTMLColour(eMinecraftColour colour);
int GetHTMLColor(eMinecraftColour colour) { return GetHTMLColour(colour); }
int GetHTMLFontSize(EHTMLFontSize size);
wstring FormatHTMLString(int iPad, const wstring &desc, int shadowColour = 0xFFFFFFFF);
wstring FormatHTMLString(int iPad, const wstring& desc, int shadowColour = 0xFFFFFFFF);
wstring EscapeHTMLString(const wstring &desc);
wstring FormatChatMessage(const wstring& desc, bool applyColor = true);
wstring GetActionReplacement(int iPad, unsigned char ucAction);
wstring GetVKReplacement(unsigned int uiVKey);
wstring GetIconReplacement(unsigned int uiIcon);
Expand Down
2 changes: 2 additions & 0 deletions Minecraft.Client/Common/UI/UIScene_HUD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ UIScene_HUD::UIScene_HUD(int iPad, void *initData, UILayer *parentLayer) : UISce
for(unsigned int i = 0; i < CHAT_LINES_COUNT; ++i)
{
m_labelChatText[i].init(L"");
IggyValueSetBooleanRS(m_labelChatText[i].getIggyValuePath(), 0, "m_bUseHtmlText", true);
}
m_labelJukebox.init(L"");
IggyValueSetBooleanRS(m_labelJukebox.getIggyValuePath(), 0, "m_bUseHtmlText", true);

addTimer(0, 100);
}
Expand Down
2 changes: 1 addition & 1 deletion Minecraft.Client/Common/UI/UIScene_HUD.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class UIScene_HUD : public UIScene, public IUIScene_HUD
bool m_bSplitscreen;

protected:
UIControl_Label m_labelChatText[CHAT_LINES_COUNT];
UIControl_HTMLLabel m_labelChatText[CHAT_LINES_COUNT];
UIControl_Label m_labelJukebox;
UIControl m_controlLabelBackground[CHAT_LINES_COUNT];
UIControl_Label m_labelDisplayName;
Expand Down
9 changes: 8 additions & 1 deletion Minecraft.Client/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,13 @@ float Gui::getOpacity(int iPad, DWORD index)
return opacityPercentage;
}

//just like java functionality it overwrites the jukebox label
void Gui::setActionBarMessage(wstring message)
{
overlayMessageString = message;
overlayMessageTime = 20 * 4; //idk how long it should last, need to check java usage
}

float Gui::getJukeboxOpacity(int iPad)
{
float t = overlayMessageTime - lastTickA;
Expand All @@ -1590,7 +1597,7 @@ void Gui::setNowPlaying(const wstring& string)
// overlayMessageString = L"Now playing: " + string;
overlayMessageString = app.GetString(IDS_NOWPLAYING) + string;
overlayMessageTime = 20 * 3;
animateOverlayMessageColor = true;
animateOverlayMessageColor = true; //appears to be unused, @DrPerkyLegit plans to add in later pr
}

void Gui::displayClientMessage(int messageId, int iPad)
Expand Down
2 changes: 2 additions & 0 deletions Minecraft.Client/Gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class Gui : public GuiComponent
wstring getMessage(int iPad, DWORD index) { return guiMessages[iPad].at(index).string; }
float getOpacity(int iPad, DWORD index);

void setActionBarMessage(wstring message); //uses jukebox label

wstring getJukeboxMessage(int iPad) { return overlayMessageString; }
float getJukeboxOpacity(int iPad);

Expand Down
2 changes: 1 addition & 1 deletion Minecraft.Client/PlayerConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ void PlayerConnection::handleChat(shared_ptr<ChatPacket> packet)
return;
}
wstring formatted = L"<" + player->name + L"> " + message;
server->getPlayers()->broadcastAll(shared_ptr<ChatPacket>(new ChatPacket(formatted)));
server->getPlayers()->broadcastAll(shared_ptr<ChatPacket>(new ChatPacket(app.FormatChatMessage(formatted, false))));
chatSpamTickCount += SharedConstants::TICKS_PER_SECOND;
if (chatSpamTickCount > SharedConstants::TICKS_PER_SECOND * 10)
{
Expand Down
1 change: 1 addition & 0 deletions Minecraft.World/ChatPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ChatPacket : public Packet, public enable_shared_from_this<ChatPacket>
e_ChatCommandTeleportMe,
e_ChatCommandTeleportToMe,

e_ChatActionBar,
};

public:
Expand Down
3 changes: 2 additions & 1 deletion Minecraft.World/SharedConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class SharedConstants
static wstring readAcceptableChars();

public:
static const int maxChatLength = 100;
static const int maxChatLength = 255;
static const int maxVisibleLength = 100; //to be changed
static wstring acceptableLetters;

static const int ILLEGAL_FILE_CHARACTERS_LENGTH = 15;
Expand Down