#include "stdafx.h" #include "ChatScreen.h" #include "ClientConnection.h" #include "Font.h" #include "MultiplayerLocalPlayer.h" #include "..\Minecraft.World\SharedConstants.h" #include "..\Minecraft.World\StringHelpers.h" #include "..\Minecraft.World\ChatPacket.h" const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters; vector ChatScreen::s_chatHistory; int ChatScreen::s_historyIndex = -1; wstring ChatScreen::s_historyDraft; bool ChatScreen::isAllowedChatChar(wchar_t c) { return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos); } int VisibleCharLength(wstring message) { static std::unordered_set validStyleCharacters = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'a', L'b', L'c', L'd', L'e', L'f', }; int results = 0; for (int i = 0; i < message.size(); i++) { wchar_t _char = message[i]; if (_char == L'§' && (i + 1) < message.size()) { wchar_t colorChar = message[i + 1]; if (validStyleCharacters.find(colorChar) != validStyleCharacters.end()) { i++; //do this so it increments 2 instead of 1 continue; } } results++; } return results; } ChatScreen::ChatScreen() { frame = 0; cursorIndex = 0; s_historyIndex = -1; } void ChatScreen::init() { Keyboard::enableRepeatEvents(true); } void ChatScreen::removed() { Keyboard::enableRepeatEvents(false); } void ChatScreen::tick() { frame++; if (cursorIndex > static_cast(message.length())) cursorIndex = static_cast(message.length()); } void ChatScreen::handlePasteRequest() { wstring pasted = Screen::getClipboard(); for (size_t i = 0; i < pasted.length() && static_cast(message.length()) < SharedConstants::maxChatLength; i++) { if (isAllowedChatChar(pasted[i])) { message.insert(cursorIndex, 1, pasted[i]); cursorIndex++; } } } void ChatScreen::applyHistoryMessage() { message = s_historyIndex >= 0 ? s_chatHistory[s_historyIndex] : s_historyDraft; cursorIndex = static_cast(message.length()); } void ChatScreen::handleHistoryUp() { if (s_chatHistory.empty()) return; if (s_historyIndex == -1) { s_historyDraft = message; s_historyIndex = static_cast(s_chatHistory.size()) - 1; } else if (s_historyIndex > 0) s_historyIndex--; applyHistoryMessage(); } void ChatScreen::handleHistoryDown() { if (s_chatHistory.empty()) return; if (s_historyIndex < static_cast(s_chatHistory.size()) - 1) s_historyIndex++; else s_historyIndex = -1; applyHistoryMessage(); } void ChatScreen::keyPressed(wchar_t ch, int eventKey) { if (eventKey == Keyboard::KEY_ESCAPE) { minecraft->setScreen(nullptr); return; } if (eventKey == Keyboard::KEY_RETURN) { wstring trim = trimString(message); if (trim.length() > 0) { if (!minecraft->handleClientSideCommand(trim)) { MultiplayerLocalPlayer* mplp = dynamic_cast(minecraft->player.get()); if (mplp && mplp->connection) mplp->connection->send(shared_ptr(new ChatPacket(trim))); } if (s_chatHistory.empty() || s_chatHistory.back() != trim) { s_chatHistory.push_back(trim); if (s_chatHistory.size() > CHAT_HISTORY_MAX) s_chatHistory.erase(s_chatHistory.begin()); } } minecraft->setScreen(nullptr); return; } if (eventKey == Keyboard::KEY_UP) { handleHistoryUp(); return; } if (eventKey == Keyboard::KEY_DOWN) { handleHistoryDown(); return; } if (eventKey == Keyboard::KEY_LEFT) { if (cursorIndex > 0) cursorIndex--; return; } if (eventKey == Keyboard::KEY_RIGHT) { if (cursorIndex < static_cast(message.length())) cursorIndex++; return; } if (eventKey == Keyboard::KEY_BACK && cursorIndex > 0) { message.erase(cursorIndex - 1, 1); cursorIndex--; return; } if (isAllowedChatChar(ch) && VisibleCharLength(message) < SharedConstants::maxVisibleLength) { message.insert(cursorIndex, 1, ch); cursorIndex++; } } void ChatScreen::render(int xm, int ym, float a) { fill(2, height - 14, width - 2, height - 2, 0x80000000); const wstring prefix = L"> "; int x = 4; drawString(font, prefix, x, height - 12, 0xe0e0e0); x += font->width(prefix); wstring beforeCursor = message.substr(0, cursorIndex); wstring afterCursor = message.substr(cursorIndex); drawString(font, beforeCursor, x, height - 12, 0xe0e0e0); x += font->width(beforeCursor); if (frame / 6 % 2 == 0) drawString(font, L"_", x, height - 12, 0xe0e0e0); //todo: fix this breaking the chat color in afterString x += font->width(L"_"); drawString(font, afterCursor, x, height - 12, 0xe0e0e0); Screen::render(xm, ym, a); } void ChatScreen::mouseClicked(int x, int y, int buttonNum) { if (buttonNum == 0) { if (minecraft->gui->selectedName != L"") // 4J - was nullptr comparison { if (message.length() > 0 && message[message.length()-1]!=L' ') { message = message.substr(0, cursorIndex) + L" " + message.substr(cursorIndex); cursorIndex++; } size_t nameLen = minecraft->gui->selectedName.length(); size_t insertLen = (message.length() + nameLen <= SharedConstants::maxChatLength) ? nameLen : (SharedConstants::maxChatLength - message.length()); if (insertLen > 0) { message = message.substr(0, cursorIndex) + minecraft->gui->selectedName.substr(0, insertLen) + message.substr(cursorIndex); cursorIndex += static_cast(insertLen); } } else { Screen::mouseClicked(x, y, buttonNum); } } }