From ea65542c1b63d7ee37025837bf205e55ace0c863 Mon Sep 17 00:00:00 2001 From: Kevin <115616336+lag@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:52:28 -0600 Subject: Add Chat / Pastes / Formatting (#682) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial fixes for ContainerSetSlotPacket and CraftItemPacket * Chat: paste, history, ยง formatting, 1-9 block when open (Windows64) Made-with: Cursor * static_cast refactor --- Minecraft.Client/ChatScreen.cpp | 126 +++++++++++++++++++++++++++++++++++----- 1 file changed, 110 insertions(+), 16 deletions(-) (limited to 'Minecraft.Client/ChatScreen.cpp') diff --git a/Minecraft.Client/ChatScreen.cpp b/Minecraft.Client/ChatScreen.cpp index b68e6cac..543cab76 100644 --- a/Minecraft.Client/ChatScreen.cpp +++ b/Minecraft.Client/ChatScreen.cpp @@ -1,14 +1,27 @@ #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); +} ChatScreen::ChatScreen() { frame = 0; + cursorIndex = 0; + s_historyIndex = -1; } void ChatScreen::init() @@ -24,6 +37,50 @@ void ChatScreen::removed() 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) @@ -35,31 +92,67 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey) } if (eventKey == Keyboard::KEY_RETURN) { - wstring msg = trimString(message); - if (msg.length() > 0) + wstring trim = trimString(message); + if (trim.length() > 0) { - wstring trim = trimString(message); if (!minecraft->handleClientSideCommand(trim)) { - minecraft->player->chat(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(NULL); return; } - if (eventKey == Keyboard::KEY_BACK && message.length() > 0) message = message.substr(0, message.length() - 1); - if (allowedChars.find(ch) >= 0 && message.length() < SharedConstants::maxChatLength) + if (eventKey == Keyboard::KEY_UP) { handleHistoryUp(); return; } + if (eventKey == Keyboard::KEY_DOWN) { handleHistoryDown(); return; } + if (eventKey == Keyboard::KEY_LEFT) { - message += ch; + 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) && static_cast(message.length()) < SharedConstants::maxChatLength) + { + message.insert(cursorIndex, 1, ch); + cursorIndex++; } - } void ChatScreen::render(int xm, int ym, float a) { fill(2, height - 14, width - 2, height - 2, 0x80000000); - drawString(font, L"> " + message + (frame / 6 % 2 == 0 ? L"_" : L""), 4, height - 12, 0xe0e0e0); - + 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); + drawStringLiteral(font, beforeCursor, x, height - 12, 0xe0e0e0); + x += font->widthLiteral(beforeCursor); + if (frame / 6 % 2 == 0) + drawString(font, L"_", x, height - 12, 0xe0e0e0); + x += font->width(L"_"); + drawStringLiteral(font, afterCursor, x, height - 12, 0xe0e0e0); Screen::render(xm, ym, a); } @@ -71,13 +164,15 @@ void ChatScreen::mouseClicked(int x, int y, int buttonNum) { if (message.length() > 0 && message[message.length()-1]!=L' ') { - message += L" "; + message = message.substr(0, cursorIndex) + L" " + message.substr(cursorIndex); + cursorIndex++; } - message += minecraft->gui->selectedName; - unsigned int maxLength = SharedConstants::maxChatLength; - if (message.length() > maxLength) + 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, maxLength); + message = message.substr(0, cursorIndex) + minecraft->gui->selectedName.substr(0, insertLen) + message.substr(cursorIndex); + cursorIndex += static_cast(insertLen); } } else @@ -85,5 +180,4 @@ void ChatScreen::mouseClicked(int x, int y, int buttonNum) Screen::mouseClicked(x, y, buttonNum); } } - } \ No newline at end of file -- cgit v1.2.3