diff --git a/Minecraft.Client/ChatScreen.cpp b/Minecraft.Client/ChatScreen.cpp index 53c9072242..9d1107cb36 100644 --- a/Minecraft.Client/ChatScreen.cpp +++ b/Minecraft.Client/ChatScreen.cpp @@ -6,6 +6,8 @@ #include "..\Minecraft.World\SharedConstants.h" #include "..\Minecraft.World\StringHelpers.h" #include "..\Minecraft.World\ChatPacket.h" +#include "Windows64\KeyboardMouseInput.h" +#include "Common\UI\UIComponent_DebugUIConsole.h" const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters; vector ChatScreen::s_chatHistory; @@ -22,6 +24,12 @@ ChatScreen::ChatScreen() frame = 0; cursorIndex = 0; s_historyIndex = -1; + + if (g_KBMInput.IsKeyPressed(VK_OEM_2)) + { + message.insert(cursorIndex, 1, L'/'); + cursorIndex++; + } } void ChatScreen::init() @@ -85,24 +93,27 @@ void ChatScreen::handleHistoryDown() 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 (!trim.empty()) + { 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()); @@ -111,33 +122,121 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey) 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) + { + if (g_KBMInput.IsKeyDown(VK_CONTROL)) + { + // move left by word + while (cursorIndex > 0 && iswspace(message[cursorIndex - 1])) cursorIndex--; + while (cursorIndex > 0 && !iswspace(message[cursorIndex - 1])) cursorIndex--; + } + else if (cursorIndex > 0) + { cursorIndex--; + } return; } + if (eventKey == Keyboard::KEY_RIGHT) - { - if (cursorIndex < static_cast(message.length())) + { + int len = static_cast(message.length()); + if (g_KBMInput.IsKeyDown(VK_CONTROL)) + { + // move right by word + while (cursorIndex < len && !iswspace(message[cursorIndex])) cursorIndex++; + while (cursorIndex < len && iswspace(message[cursorIndex])) cursorIndex++; + } + else if (cursorIndex < len) + { cursorIndex++; + } return; } + if (eventKey == Keyboard::KEY_BACK && cursorIndex > 0) - { - message.erase(cursorIndex - 1, 1); - cursorIndex--; + { + std::wstring trim; + + if (g_KBMInput.IsKeyDown(VK_CONTROL)) + { + trim = L"CTRL + BACK PRESSED"; + + size_t start = cursorIndex; + + while (start > 0 && iswspace(message[start - 1])) + start--; + + while (start > 0 && !iswspace(message[start - 1])) + start--; + + message.erase(start, cursorIndex - start); + cursorIndex = start; + } + else + { + trim = L"BACK PRESSED"; + + message.erase(cursorIndex - 1, 1); + cursorIndex--; + } + + // PRINTING OUT WHEN TRIGGERED FOR DEBUGGING + + wstring trim1 = trimString(trim); + + //if (!minecraft->handleClientSideCommand(trim1)) + //{ + // MultiplayerLocalPlayer* mplp = dynamic_cast(minecraft->player.get()); + // if (mplp && mplp->connection) + // mplp->connection->send(std::make_shared(trim1)); + //} + return; } + + // NEEDS IMPLEMENTING (CTRL + A TO SELECT ALL) + + if (g_KBMInput.IsKeyDown(VK_CONTROL) && g_KBMInput.IsKeyPressed('A')) + { + return; + } + + // NEEDS IMPLEMENTING (SHIFT + LEFT ARROW TO SELECT CHARACTER) + + if (g_KBMInput.IsKeyDown(VK_SHIFT) && g_KBMInput.IsKeyPressed(VK_LEFT)) + { + return; + } + + // NEEDS IMPLEMENTING (SHIFT + RIGHT ARROW TO SELECT CHARACTER) + + if (g_KBMInput.IsKeyDown(VK_SHIFT) && g_KBMInput.IsKeyPressed(VK_RIGHT)) + { + return; + } + + // NEEDS IMPLEMENTING (TAB TO AUTOFILL USERNAMES e.g( et > TAB > ethxnblxd )) + // if theres multiple usernames then make a gui above the chat window and cycle through them by using tab) + + if (eventKey == Keyboard::KEY_TAB) + { + return; + } + if (isAllowedChatChar(ch) && static_cast(message.length()) < SharedConstants::maxChatLength) - { + { message.insert(cursorIndex, 1, ch); cursorIndex++; } } + +// NEEDS IMPLEMENTING (BLUE CHARACTER SELECTION RENDERING) + void ChatScreen::render(int xm, int ym, float a) { fill(2, height - 14, width - 2, height - 2, 0x80000000); diff --git a/Minecraft.Client/Common/App_enums.h b/Minecraft.Client/Common/App_enums.h index 15a179787b..aa27254f90 100644 --- a/Minecraft.Client/Common/App_enums.h +++ b/Minecraft.Client/Common/App_enums.h @@ -862,6 +862,7 @@ enum EControllerActions MINECRAFT_ACTION_INVENTORY, MINECRAFT_ACTION_PAUSEMENU, MINECRAFT_ACTION_DROP, + MINECRAFT_ACTION_DROPALL, MINECRAFT_ACTION_SNEAK_TOGGLE, MINECRAFT_ACTION_CRAFTING, MINECRAFT_ACTION_RENDER_THIRD_PERSON, diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 1ba432fd04..3a9f83b7ca 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -36,6 +36,8 @@ #include "FrustumCuller.h" #include "Camera.h" +#include "chrono" + #include "..\Minecraft.World\MobEffect.h" #include "..\Minecraft.World\Difficulty.h" #include "..\Minecraft.World\net.minecraft.world.level.h" @@ -1509,8 +1511,40 @@ void Minecraft::run_middle() } } - if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DROP)) - localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed |= 1LL << MINECRAFT_ACTION_DROPALL; + } + + else if (down) + // CHANGED FROM IsKeyPressed SO YOU CAN HOLD TO DROP (after 0.3 sec delay). + { + auto now = std::chrono::steady_clock::now(); + + if (!wasDown) + { + // first press + localplayers[i]->ullButtonsPressed |= 1LL << MINECRAFT_ACTION_DROP; + pressTime = now; + } + else + { + float held = std::chrono::duration(now - pressTime).count(); + + if (held > 0.3f) + { + localplayers[i]->ullButtonsPressed |= 1LL << MINECRAFT_ACTION_DROP; + } + } + } + + wasDown = down; if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_CRAFTING) || g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_CRAFTING_ALT)) { @@ -1524,18 +1558,27 @@ void Minecraft::run_middle() } } - for (int slot = 0; slot < 9; slot++) + // PREVENTS SWITCHING HOTBAR SLOTS WHEN IN MENUS + + if (!ui.GetMenuDisplayed(0)) { - if (g_KBMInput.IsKeyPressed('1' + slot)) + for (int slot = 0; slot < 9; slot++) { - if (localplayers[i]->inventory) - localplayers[i]->inventory->selected = slot; + if (g_KBMInput.IsKeyPressed('1' + slot)) + { + if (localplayers[i]->inventory) + localplayers[i]->inventory->selected = slot; + } } } + } + // Utility keys always work regardless of KBM active state - if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.GetMenuDisplayed(i)) + Minecraft* pMinecraft = Minecraft::GetInstance(); + + if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.GetMenuDisplayed(i) && pMinecraft->screen == NULL) { localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed&(1LL<isInputAllowed(MINECRAFT_ACTION_INVENTORY)) { shared_ptr player = Minecraft::GetInstance()->player; - if (!player->isRiding()) - { - ui.PlayUISFX(eSFX_Press); - } + ui.PlayUISFX(eSFX_Press); if(gameMode->isServerControlledInventory()) { @@ -3805,6 +3876,11 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) player->drop(); } + if((player->ullButtonsPressed&(1LL<isInputAllowed(MINECRAFT_ACTION_DROPALL)) + { + player->dropall(); + } + uint64_t ullButtonsPressed=player->ullButtonsPressed; bool selected = false; diff --git a/Minecraft.Client/MultiPlayerLocalPlayer.cpp b/Minecraft.Client/MultiPlayerLocalPlayer.cpp index aef7898f25..038963db6f 100644 --- a/Minecraft.Client/MultiPlayerLocalPlayer.cpp +++ b/Minecraft.Client/MultiPlayerLocalPlayer.cpp @@ -179,6 +179,12 @@ shared_ptr MultiplayerLocalPlayer::drop() return nullptr; } +shared_ptr MultiplayerLocalPlayer::dropall() +{ + connection->send(std::make_shared(PlayerActionPacket::DROP_ALL_ITEMS, 0, 0, 0, 0)); + return nullptr; +} + void MultiplayerLocalPlayer::reallyDrop(shared_ptr itemEntity) { } diff --git a/Minecraft.Client/MultiPlayerLocalPlayer.h b/Minecraft.Client/MultiPlayerLocalPlayer.h index e660a96a20..286e48ec82 100644 --- a/Minecraft.Client/MultiPlayerLocalPlayer.h +++ b/Minecraft.Client/MultiPlayerLocalPlayer.h @@ -36,6 +36,9 @@ class MultiplayerLocalPlayer : public LocalPlayer using Player::drop; virtual shared_ptr drop(); + + using Player::dropall; + virtual shared_ptr dropall(); protected: virtual void reallyDrop(shared_ptr itemEntity); public: diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.h b/Minecraft.Client/Windows64/KeyboardMouseInput.h index 5c406983f5..5569e684b3 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.h +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.h @@ -26,6 +26,7 @@ class KeyboardMouseInput static const int KEY_CRAFTING = 'C'; static const int KEY_CRAFTING_ALT = 'R'; static const int KEY_CHAT = 'T'; + static const int KEY_SLASHCOMMANDCHAT = VK_OEM_2; static const int KEY_CONFIRM = VK_RETURN; static const int KEY_CANCEL = VK_ESCAPE; static const int KEY_PAUSE = VK_ESCAPE; diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 81430ffcc7..bc65929ec5 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -1802,7 +1802,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, } // TAB opens game info menu. - Vvis :3 - Updated by detectiveren - if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_HOST_SETTINGS) && !ui.GetMenuDisplayed(0)) + if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_HOST_SETTINGS) && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL) { if (Minecraft* pMinecraft = Minecraft::GetInstance()) { @@ -1821,6 +1821,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, SetFocus(g_hWnd); } + else if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_SLASHCOMMANDCHAT) && app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL) + // Needs to set the message with "/" when pressed. + { + g_KBMInput.ClearCharBuffer(); + pMinecraft->setScreen(new ChatScreen()); + SetFocus(g_hWnd); + } + #if 0 // has the game defined profile data been changed (by a profile load) if(app.uiGameDefinedDataChangedBitmask!=0) diff --git a/Minecraft.World/AbstractContainerMenu.cpp b/Minecraft.World/AbstractContainerMenu.cpp index c98fc22c50..04e2b6a14f 100644 --- a/Minecraft.World/AbstractContainerMenu.cpp +++ b/Minecraft.World/AbstractContainerMenu.cpp @@ -157,8 +157,8 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto shared_ptr clickedEntity = nullptr; shared_ptr inventory = player->inventory; - if (slotIndex < 0 || slotIndex >= (int)slots.size()) - return nullptr; + //if (slotIndex < 0 || slotIndex >= (int)slots.size()) + // return nullptr; if (clickType == CLICK_QUICK_CRAFT) { diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index 00c7148e41..94308ed806 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -1205,6 +1205,56 @@ shared_ptr Player::drop(shared_ptr item, bool randomly return thrownItem; } +shared_ptr Player::dropall(bool all) +{ + return dropall(inventory->removeItem(inventory->selected, all && inventory->getSelected() != nullptr ? inventory->getSelected()->count : inventory->getSelected()->count), false); +} + +shared_ptr Player::dropall(shared_ptr item) +{ + return dropall(item, false); +} + +shared_ptr Player::dropall(shared_ptr item, bool randomly) +{ + if (item == nullptr) return nullptr; + if (item->count == 0) return nullptr; + + shared_ptr thrownItem = std::make_shared(level, x, y - 0.3f + getHeadHeight(), z, item); + thrownItem->throwTime = 20 * 2; + + thrownItem->setThrower(getName()); + + float pow = 0.1f; + if (randomly) + { + float _pow = random->nextFloat() * 0.5f; + float dir = random->nextFloat() * PI * 2; + thrownItem->xd = -sin(dir) * _pow; + thrownItem->zd = cos(dir) * _pow; + thrownItem->yd = 0.2f; + + } + else + { + pow = 0.3f; + thrownItem->xd = -sin(yRot / 180 * PI) * cos(xRot / 180 * PI) * pow; + thrownItem->zd = cos(yRot / 180 * PI) * cos(xRot / 180 * PI) * pow; + thrownItem->yd = -sin(xRot / 180 * PI) * pow + 0.1f; + pow = 0.02f; + + float dir = random->nextFloat() * PI * 2; + pow *= random->nextFloat(); + thrownItem->xd += cos(dir) * pow; + thrownItem->yd += (random->nextFloat() - random->nextFloat()) * 0.1f; + thrownItem->zd += sin(dir) * pow; + } + + reallyDrop(thrownItem); + + return thrownItem; +} + void Player::reallyDrop(shared_ptr thrownItem) { diff --git a/Minecraft.World/Player.h b/Minecraft.World/Player.h index 2e223a1e55..8372bc036a 100644 --- a/Minecraft.World/Player.h +++ b/Minecraft.World/Player.h @@ -201,6 +201,9 @@ class Player : public LivingEntity, public CommandSender, public ScoreHolder shared_ptr drop(shared_ptr item); shared_ptr drop(shared_ptr item, bool randomly); + virtual shared_ptr dropall(bool all); + shared_ptr dropall(shared_ptr item); + shared_ptr dropall(shared_ptr item, bool randomly); protected: virtual void reallyDrop(shared_ptr thrownItem); diff --git a/Minecraft.World/SharedConstants.cpp b/Minecraft.World/SharedConstants.cpp index 00ff3a0510..9e6743606e 100644 --- a/Minecraft.World/SharedConstants.cpp +++ b/Minecraft.World/SharedConstants.cpp @@ -32,9 +32,13 @@ wstring SharedConstants::readAcceptableChars() bool SharedConstants::isAllowedChatCharacter(char ch) { - //return ch != 'ยง' && (acceptableLetters.indexOf(ch) >= 0 || (int) ch > 32); - // 4J Unused - return true; + // SHOULD block control chars but it doesnt for some reason... (ctrl+backspace) + // also removed the S symbol because we can just make color codes not work in chat. + + if (std::iscntrl(static_cast(ch))) + return false; + + return acceptableLetters.find(ch) != std::string::npos || std::isprint(static_cast(ch)); } wstring SharedConstants::acceptableLetters;