From 1d4294dd94e2e9bea6b6a9f391111b19bacba43c Mon Sep 17 00:00:00 2001 From: Wilyicaro Date: Tue, 24 Feb 2026 04:08:08 -0300 Subject: [PATCH 1/6] -Added input hotswap, tested between controller and kbm for now -Added a HashMap implementation in common, and implemented in some places -Now, Console UI Theme tooltips will be accurate -Now, sneaking with the controller will be toggleable -Now, the UI Theme will be applied when exiting the options screen -Now, the font rendering will be faster -Now, Vertical Layout will always navigate to the next element when scrolling down -Fixed Skeleton arrow shooting not accounting the head height -Fixed item swapping not calling slot changed, not changing the crafting result -Fixed Vertical Layout labels being selectable -Fixed not being able to navigate if there aren't selected elements --- game/assets/materials/ui.material | 2 +- .../xinput/GameControllerHandler_xinput.cpp | 12 +- platforms/sdl/base/AppPlatform_sdl.cpp | 53 ++- platforms/sdl/base/AppPlatform_sdl.hpp | 2 + platforms/sdl/sdl2/main.cpp | 6 +- platforms/windows/main.cpp | 3 +- .../windows/projects/Common/Common.vcxproj | 1 + .../projects/Common/Common.vcxproj.filters | 3 + source/client/app/Minecraft.cpp | 198 +++++---- source/client/app/NinecraftApp.cpp | 17 +- source/client/gui/Gui.cpp | 12 +- source/client/gui/Gui.hpp | 2 +- source/client/gui/GuiElement.cpp | 2 +- source/client/gui/GuiElement.hpp | 2 +- source/client/gui/Screen.cpp | 70 ++- source/client/gui/Screen.hpp | 5 +- source/client/gui/ScreenChooser.cpp | 1 - source/client/gui/VerticalLayout.cpp | 44 +- source/client/gui/VerticalLayout.hpp | 2 + source/client/gui/components/OptionList.cpp | 3 +- source/client/gui/components/TextBox.cpp | 8 +- source/client/gui/components/TextBox.hpp | 2 +- source/client/gui/screens/ChatScreen.cpp | 11 +- source/client/gui/screens/ChatScreen.hpp | 3 +- source/client/gui/screens/CreditsScreen.cpp | 4 +- source/client/gui/screens/CreditsScreen.hpp | 2 +- .../screens/IngameBlockSelectionScreen.cpp | 11 +- .../screens/IngameBlockSelectionScreen.hpp | 3 +- source/client/gui/screens/OptionsScreen.cpp | 10 + source/client/gui/screens/OptionsScreen.hpp | 1 + .../gui/screens/OptionsScreen_Console.cpp | 13 +- .../gui/screens/OptionsScreen_Console.hpp | 1 + source/client/gui/screens/PauseScreen.cpp | 10 + source/client/gui/screens/PauseScreen.hpp | 9 +- .../gui/screens/PauseScreen_Console.cpp | 12 +- .../gui/screens/PauseScreen_Console.hpp | 1 + .../client/gui/screens/SelectWorldScreen.cpp | 11 +- .../client/gui/screens/SelectWorldScreen.hpp | 2 +- source/client/gui/screens/StartMenuScreen.cpp | 12 +- source/client/gui/screens/StartMenuScreen.hpp | 1 + .../gui/screens/StartMenuScreen_Console.cpp | 12 +- .../gui/screens/StartMenuScreen_Console.hpp | 1 + .../gui/screens/inventory/ContainerScreen.cpp | 30 +- .../gui/screens/inventory/ContainerScreen.hpp | 2 +- source/client/options/Options.cpp | 95 ++-- source/client/options/Options.hpp | 57 ++- .../player/input/ControllerMoveInput.cpp | 10 +- .../player/input/ControllerMoveInput.hpp | 2 +- .../client/player/input/CustomInputHolder.cpp | 9 +- .../client/player/input/CustomInputHolder.hpp | 4 +- source/client/player/input/GameController.hpp | 1 + .../player/input/GameControllerHandler.hpp | 7 +- .../player/input/GameControllerManager.cpp | 66 +++ .../player/input/GameControllerManager.hpp | 9 + source/client/player/input/IInputHolder.cpp | 7 + source/client/player/input/IInputHolder.hpp | 13 + source/client/player/input/IMoveInput.cpp | 2 +- source/client/player/input/IMoveInput.hpp | 4 +- source/client/player/input/Keyboard.cpp | 6 + source/client/player/input/KeyboardInput.cpp | 36 +- source/client/player/input/KeyboardInput.hpp | 2 +- source/client/player/input/MouseDevice.cpp | 7 + source/client/player/input/Multitouch.cpp | 2 + .../client/player/input/TouchInputHolder.cpp | 5 + .../client/player/input/TouchInputHolder.hpp | 1 + .../player/input/TouchscreenInput_TestFps.cpp | 2 +- .../player/input/TouchscreenInput_TestFps.hpp | 2 +- source/client/renderer/Font.cpp | 58 ++- source/client/renderer/Font.hpp | 2 + source/client/renderer/GameRenderer.cpp | 2 +- source/common/utility/HashMap.hpp | 413 ++++++++++++++++++ source/nbt/CompoundTag.cpp | 37 +- source/nbt/CompoundTag.hpp | 3 +- source/world/entity/Arrow.hpp | 2 +- source/world/entity/Skeleton.cpp | 2 +- source/world/inventory/ContainerMenu.cpp | 4 +- source/world/item/ItemStack.cpp | 6 +- source/world/level/Level.cpp | 4 +- source/world/level/Level.hpp | 4 +- 79 files changed, 1173 insertions(+), 325 deletions(-) create mode 100644 source/common/utility/HashMap.hpp diff --git a/game/assets/materials/ui.material b/game/assets/materials/ui.material index 73b1858d0..7c086d6ab 100644 --- a/game/assets/materials/ui.material +++ b/game/assets/materials/ui.material @@ -35,7 +35,7 @@ "states": ["DisableCulling"] }, - "ui_text:ui_texture_and_color": { + "ui_text:ui_textured_and_glcolor": { "fragmentShader": "shaders/text.fragment" }, diff --git a/platforms/input/xinput/GameControllerHandler_xinput.cpp b/platforms/input/xinput/GameControllerHandler_xinput.cpp index 02701c6f2..8cc544280 100644 --- a/platforms/input/xinput/GameControllerHandler_xinput.cpp +++ b/platforms/input/xinput/GameControllerHandler_xinput.cpp @@ -42,11 +42,6 @@ void GameControllerHandler_xinput::_initButtonMap() m[XINPUT_GAMEPAD_START] = GameController::BUTTON_START; } -Keyboard::KeyState _getKeyState(bool value) -{ - return value ? Keyboard::DOWN : Keyboard::UP; -} - void GameControllerHandler_xinput::_processButton(GameController::ID controllerId, const XINPUT_STATE& state, GameController::NativeButtonID nativeBtn, GameController::EngineButtonID engineBtn, bool& joinGameAlreadyFired) { bool bButtonPressed = (state.Gamepad.wButtons & nativeBtn) != 0; @@ -63,8 +58,7 @@ void GameControllerHandler_xinput::_processButton(GameController::ID controllerI joinGameAlreadyFired = true; } - // @TODO: should call GameControllerManager::feedButton() instead - Keyboard::feed(_getKeyState(bButtonPressed), engineBtn); + GameControllerManager::feedButton(btnState, engineBtn); lastBtnState = btnState; } @@ -95,9 +89,9 @@ void GameControllerHandler_xinput::refresh() { XINPUT_STATE& inputState = m_inputStates.m_inputState[id]; bool joinGameAlreadyFired = false; - for (ButtonIDMap::const_iterator it = m_buttonIdMap.begin(); it != m_buttonIdMap.end(); it++) + for (ButtonIDMap::Iterator it = m_buttonIdMap.begin(); it != m_buttonIdMap.end(); it++) { - _processButton(id, inputState, it->first, it->second, joinGameAlreadyFired); + _processButton(id, inputState, it.key(), it.value(), joinGameAlreadyFired); } GameControllerManager::feedTrigger(1, (float)inputState.Gamepad.bLeftTrigger / 255.0f); diff --git a/platforms/sdl/base/AppPlatform_sdl.cpp b/platforms/sdl/base/AppPlatform_sdl.cpp index ecacb41fb..3f586caae 100644 --- a/platforms/sdl/base/AppPlatform_sdl.cpp +++ b/platforms/sdl/base/AppPlatform_sdl.cpp @@ -312,7 +312,7 @@ void AppPlatform_sdl::handleKeyEvent(const SDL_Event& event) void AppPlatform_sdl::handleControllerButtonEvent(SDL_JoystickID controllerIndex, uint8_t button, uint8_t state) { // Normal Key Press - Keyboard::feed(GetKeyState(state), button); + GameControllerManager::feedButton(state == SDL_PRESSED ? GameController::BTN_STATE_DOWN : GameController::BTN_STATE_UP, GetEngineButton(button)); } void AppPlatform_sdl::handleControllerAxisEvent(SDL_JoystickID controllerIndex, uint8_t axis, int16_t value) @@ -492,3 +492,54 @@ Keyboard::KeyState AppPlatform_sdl::GetKeyState(uint8_t state) return Keyboard::DOWN; } } + +GameController::EngineButtonID AppPlatform_sdl::GetEngineButton(uint8_t button) +{ + switch (button) + { + case SDL_CONTROLLER_BUTTON_A: + return GameController::BUTTON_A; + case SDL_CONTROLLER_BUTTON_B: + return GameController::BUTTON_B; + case SDL_CONTROLLER_BUTTON_X: + return GameController::BUTTON_X; + case SDL_CONTROLLER_BUTTON_Y: + return GameController::BUTTON_Y; + case SDL_CONTROLLER_BUTTON_DPAD_UP: + return GameController::BUTTON_DPAD_UP; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + return GameController::BUTTON_DPAD_DOWN; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + return GameController::BUTTON_DPAD_LEFT; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + return GameController::BUTTON_DPAD_RIGHT; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: + return GameController::BUTTON_LEFTSTICK; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: + return GameController::BUTTON_RIGHTSTICK; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: + return GameController::BUTTON_LEFTSHOULDER; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: + return GameController::BUTTON_RIGHTSHOULDER; + case SDL_CONTROLLER_BUTTON_BACK: + return GameController::BUTTON_BACK; + case SDL_CONTROLLER_BUTTON_START: + return GameController::BUTTON_START; + case SDL_CONTROLLER_BUTTON_GUIDE: + return GameController::BUTTON_GUIDE; + case SDL_CONTROLLER_BUTTON_MISC1: + return GameController::BUTTON_MISC1; + case SDL_CONTROLLER_BUTTON_PADDLE1: + return GameController::BUTTON_PADDLE1; + case SDL_CONTROLLER_BUTTON_PADDLE2: + return GameController::BUTTON_PADDLE2; + case SDL_CONTROLLER_BUTTON_PADDLE3: + return GameController::BUTTON_PADDLE3; + case SDL_CONTROLLER_BUTTON_PADDLE4: + return GameController::BUTTON_PADDLE4; + case SDL_CONTROLLER_BUTTON_TOUCHPAD: + return GameController::BUTTON_TOUCHPAD; + default: + return GameController::BUTTON_NONE; + } +} diff --git a/platforms/sdl/base/AppPlatform_sdl.hpp b/platforms/sdl/base/AppPlatform_sdl.hpp index c93d4f4b2..0bdf38fd9 100644 --- a/platforms/sdl/base/AppPlatform_sdl.hpp +++ b/platforms/sdl/base/AppPlatform_sdl.hpp @@ -8,6 +8,7 @@ #include "client/player/input/Mouse.hpp" #include "client/player/input/Keyboard.hpp" +#include "client/player/input/GameController.hpp" #include "common/Logger.hpp" class AppPlatform_sdl : public AppPlatform @@ -72,6 +73,7 @@ class AppPlatform_sdl : public AppPlatform static MouseButtonType GetMouseButtonType(uint8_t button); static bool GetMouseButtonState(const SDL_Event& event); static Keyboard::KeyState GetKeyState(uint8_t state); + static GameController::EngineButtonID GetEngineButton(uint8_t button); protected: ImageData m_iconImage; diff --git a/platforms/sdl/sdl2/main.cpp b/platforms/sdl/sdl2/main.cpp index 3cbaabbe5..c0183b7b3 100644 --- a/platforms/sdl/sdl2/main.cpp +++ b/platforms/sdl/sdl2/main.cpp @@ -233,7 +233,8 @@ static void handle_events() float x = event.button.x * scale; float y = event.button.y * scale; Mouse::feed(type, state, x, y); - Multitouch::feed(type, state, x, y, 0); + if (g_pAppPlatform->isTouchscreen()) + Multitouch::feed(type, state, x, y, 0); } break; } @@ -244,7 +245,8 @@ static void handle_events() float scale = g_fPointToPixelScale; float x = event.motion.x * scale; float y = event.motion.y * scale; - Multitouch::feed(MOUSE_BUTTON_NONE, false, x, y, 0); + if (g_pAppPlatform->isTouchscreen()) + Multitouch::feed(MOUSE_BUTTON_NONE, false, x, y, 0); Mouse::feed(MOUSE_BUTTON_NONE, false, x, y); g_pAppPlatform->setMouseDiff(event.motion.xrel * scale, event.motion.yrel * scale); } diff --git a/platforms/windows/main.cpp b/platforms/windows/main.cpp index 00f703ea1..4848500a9 100644 --- a/platforms/windows/main.cpp +++ b/platforms/windows/main.cpp @@ -61,7 +61,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) posY = Mouse::getY(); } Mouse::feed(buttonType, buttonState, posX, posY); - Multitouch::feed(buttonType, buttonState, posX, posY, 0); + if (g_AppPlatform.isTouchscreen()) + Multitouch::feed(buttonType, buttonState, posX, posY, 0); break; } diff --git a/platforms/windows/projects/Common/Common.vcxproj b/platforms/windows/projects/Common/Common.vcxproj index a497af7e0..9ee2aa6ef 100644 --- a/platforms/windows/projects/Common/Common.vcxproj +++ b/platforms/windows/projects/Common/Common.vcxproj @@ -115,6 +115,7 @@ + diff --git a/platforms/windows/projects/Common/Common.vcxproj.filters b/platforms/windows/projects/Common/Common.vcxproj.filters index 56d68fb15..fdd8109f3 100644 --- a/platforms/windows/projects/Common/Common.vcxproj.filters +++ b/platforms/windows/projects/Common/Common.vcxproj.filters @@ -127,5 +127,8 @@ Header Files\Threading + + Header Files\Utility + \ No newline at end of file diff --git a/source/client/app/Minecraft.cpp b/source/client/app/Minecraft.cpp index 27a162a15..d1713f144 100644 --- a/source/client/app/Minecraft.cpp +++ b/source/client/app/Minecraft.cpp @@ -181,14 +181,21 @@ void Minecraft::_reloadInput() if (isTouchscreen()) { m_pInputHolder = new TouchInputHolder(this, getOptions()); + + if (m_bGrabbedMouse) + platform()->setMouseGrabbed(false); } else if (useController()) { m_pInputHolder = new CustomInputHolder( new ControllerMoveInput(getOptions()), new ControllerTurnInput(), - new ControllerBuildInput() + new ControllerBuildInput(), + true ); + + if (m_bGrabbedMouse) + platform()->setMouseGrabbed(false); } else { @@ -197,6 +204,9 @@ void Minecraft::_reloadInput() new MouseTurnInput(this), new MouseBuildInput() ); + + if (m_bGrabbedMouse) + platform()->setMouseGrabbed(true); } m_mouseHandler.setTurnInput(m_pInputHolder->getTurnInput()); @@ -262,7 +272,6 @@ void Minecraft::recenterMouse() void Minecraft::setScreen(Screen* pScreen) { - float lastScale = getBestScaleForThisScreenSize(Minecraft::width, Minecraft::height); #ifndef ORIGINAL_CODE if (pScreen == nullptr && !isLevelGenerated()) { @@ -277,13 +286,15 @@ void Minecraft::setScreen(Screen* pScreen) return; } - if (pScreen && pScreen->isErrorScreen()) + if (pScreen && (pScreen->isErrorScreen() || pScreen->isInvalid(this))) { // not in original delete pScreen; return; } + float lastScale = getBestScaleForThisScreenSize(Minecraft::width, Minecraft::height); + if (m_pScreen) { m_pScreen->removed(); @@ -361,17 +372,17 @@ bool Minecraft::isOnlineClient() const bool Minecraft::isTouchscreen() const { - return m_bIsTouchscreen; + return IInputHolder::activeType == IInputHolder::TOUCHSCREEN; } bool Minecraft::useSplitControls() const { - return !m_bIsTouchscreen || getOptions()->m_splitControls.get(); + return !isTouchscreen() || getOptions()->m_splitControls.get(); } bool Minecraft::useController() const { - return m_pPlatform->hasGamepad() && getOptions()->m_bUseController.get(); + return m_pPlatform->hasGamepad() && (IInputHolder::activeType == IInputHolder::CONTROLLER || getOptions()->m_bUseController.get()); } void Minecraft::setGameMode(GameType gameType) @@ -505,6 +516,9 @@ void Minecraft::handleBuildAction(const BuildActionIntention& action) void Minecraft::tickInput() { + if (!m_pInputHolder->allowsType(IInputHolder::activeType)) + _reloadInput(); + if (m_pScreen) { if (!m_pScreen->m_bPassEvents) @@ -550,93 +564,132 @@ void Minecraft::tickInput() #endif } - while (Keyboard::next()) + if (useController()) { - int keyCode = Keyboard::getEventKey(); - bool bPressed = Keyboard::getEventKeyState() == 1; + //Clearing, so the events don't accumulate + Keyboard::reset(); - m_pLocalPlayer->m_pMoveInput->setKey(keyCode, bPressed); - - if (bPressed) + while (GameControllerManager::next()) { - m_pGui->handleKeyPressed(keyCode); + if (!useController()) continue; + GameController::EngineButtonID button = GameControllerManager::getEventButton(); + bool bPressed = GameControllerManager::getEventButtonState() == GameController::BTN_STATE_DOWN; - for (int i = 0; i < m_pGui->getNumUsableSlots(); i++) - { - if (getOptions()->isKey(eKeyMappingIndex(KM_SLOT_1 + i), keyCode)) - m_pLocalPlayer->m_pInventory->selectSlot(i); - } + if (bPressed) + m_pGui->handleControlPressed(ControlBind(-1, button)); - if (getOptions()->isKey(KM_TOGGLE3RD, keyCode)) + for (size_t i = 0; i < KM_COUNT; ++i) { - getOptions()->m_thirdPerson.toggle(); + eControlMappingIndex ctrl = (eControlMappingIndex)i; + if (!getOptions()->getControl(ctrl).isButton(button)) continue; + + m_pLocalPlayer->m_pMoveInput->setKey(ctrl, bPressed); + if (bPressed) + getOptions()->getControlMapping(ctrl).pressed(); + else + getOptions()->getControlMapping(ctrl).reset(); } - else if (getOptions()->isKey(KM_MENU_PAUSE, keyCode)) + } + } + else + { + //Clearing, so the events don't accumulate + GameControllerManager::clear(); + while (Keyboard::next()) + { + int keyCode = Keyboard::getEventKey(); + bool bPressed = Keyboard::getEventKeyState() == Keyboard::DOWN; + + if (bPressed) + m_pGui->handleControlPressed(ControlBind(keyCode, GameController::BUTTON_NONE)); + + for (size_t i = 0; i < KM_COUNT; ++i) { - handleBack(false); + eControlMappingIndex ctrl = (eControlMappingIndex)i; + if (!getOptions()->isKey(ctrl, keyCode)) continue; + + m_pLocalPlayer->m_pMoveInput->setKey(ctrl, bPressed); + if (bPressed) + getOptions()->getControlMapping(ctrl).pressed(); + else + getOptions()->getControlMapping(ctrl).reset(); } - else if (getOptions()->isKey(KM_DROP, keyCode)) + + if (getOptions()->field_19) + continue; + + // @TODO: Replace with KeyboardBuildInput + if (!useController() && getTimeMs() - field_2B4 <= 200) { - ItemStack& item = m_pLocalPlayer->m_pInventory->getSelected(); - if (!item.isEmpty()) + if (getOptions()->isKey(KM_DESTROY, keyCode) && bPressed) { - ItemStack itemDrop(item); - itemDrop.m_count = 1; - - if (m_pLocalPlayer->isSurvival()) - item.shrink(1); + BuildActionIntention intention(BuildActionIntention::KEY_DESTROY); + handleBuildAction(intention); + } - m_pLocalPlayer->drop(itemDrop); + if (getOptions()->isKey(KM_PLACE, keyCode) && bPressed) + { + BuildActionIntention intention(BuildActionIntention::KEY_USE); + handleBuildAction(intention); } } - else if (getOptions()->isKey(KM_TOGGLEGUI, keyCode)) - { - getOptions()->m_hideGui.toggle(); - } - else if (getOptions()->isKey(KM_TOGGLEDEBUG, keyCode)) - { - getOptions()->m_debugText.toggle(); - } -#ifdef ENH_ALLOW_AO_TOGGLE - else if (getOptions()->isKey(KM_TOGGLEAO, keyCode)) - { - // Toggle ambient occlusion. - getOptions()->m_ambientOcclusion.toggle(); - Minecraft::useAmbientOcclusion = getOptions()->m_ambientOcclusion.get(); - m_pLevelRenderer->allChanged(); - } -#endif } + } - if (getOptions()->field_19) - continue; + for (int i = 0; i < m_pGui->getNumUsableSlots(); i++) + { + while (getOptions()->getControlMapping(eControlMappingIndex(KM_SLOT_1 + i)).consume()) + m_pLocalPlayer->m_pInventory->selectSlot(i); + } + + while (getOptions()->getControlMapping(KM_TOGGLE3RD).consume()) + { + getOptions()->m_thirdPerson.toggle(); + } - // @TODO: Replace with KeyboardBuildInput - if (!useController() && getTimeMs() - field_2B4 <= 200) + while (getOptions()->getControlMapping(KM_MENU_PAUSE).consume()) + { + handleBack(false); + } + + while (getOptions()->getControlMapping(KM_DROP).consume()) + { + ItemStack& item = m_pLocalPlayer->m_pInventory->getSelected(); + if (!item.isEmpty()) { - if (getOptions()->getKey(KM_DESTROY) == keyCode && bPressed) - { - BuildActionIntention intention(BuildActionIntention::KEY_DESTROY); - handleBuildAction(intention); - } + ItemStack itemDrop(item); + itemDrop.m_count = 1; - if (getOptions()->getKey(KM_PLACE) == keyCode && bPressed) - { - BuildActionIntention intention(BuildActionIntention::KEY_USE); - handleBuildAction(intention); - } + item.shrink(1); + + m_pLocalPlayer->drop(itemDrop); } } + while (getOptions()->getControlMapping(KM_TOGGLEGUI).consume()) + { + getOptions()->m_hideGui.toggle(); + } + + while (getOptions()->getControlMapping(KM_TOGGLEDEBUG).consume()) + { + getOptions()->m_debugText.toggle(); + } +#ifdef ENH_ALLOW_AO_TOGGLE + while (getOptions()->getControlMapping(KM_TOGGLEAO).consume()) + { + // Toggle ambient occlusion. + getOptions()->m_ambientOcclusion.toggle(); + m_pLevelRenderer->allChanged(); + } +#endif + BuildActionIntention bai; IBuildInput* buildInput = m_pInputHolder->getBuildInput(); if (buildInput && buildInput->tickBuild(m_pLocalPlayer, &bai)) handleBuildAction(bai); field_2B4 = getTimeMs(); - - Keyboard::reset(); - Mouse::reset(); } void Minecraft::tickMouse() @@ -847,6 +900,9 @@ void Minecraft::tick() m_pScreen->tick(); Multitouch::reset(); + + // Actually pause the game, because fuck bedrock edition + m_bIsGamePaused = !isOnline() || (m_pLevel && m_pLevel->m_players.size() == 1 && m_pScreen && m_pScreen->isPauseScreen()); } } @@ -1001,13 +1057,12 @@ void Minecraft::prepareLevel(const std::string& unused) void Minecraft::sizeUpdate(int newWidth, int newHeight) { // re-calculate the GUI scale. - Gui::GuiScale = getBestScaleForThisScreenSize(newWidth, newHeight) / getRenderScaleMultiplier(); + Gui::GuiScale = getBestScaleForThisScreenSize(newWidth, newHeight) / getRenderScaleMultiplier(); // The ceil gives an extra pixel to the screen's width and height, in case the GUI scale doesn't // divide evenly into width or height, so that none of the game screen is uncovered. + Gui::GuiWidth = ceilf(Minecraft::width * Gui::GuiScale); Gui::GuiHeight = ceilf(Minecraft::height * Gui::GuiScale); - Gui::GuiScale = float(Gui::GuiHeight) / height; - Gui::GuiWidth = ceilf(Minecraft::width * Gui::GuiScale); if (m_pScreen) m_pScreen->setSize( @@ -1049,7 +1104,7 @@ float Minecraft::getBestScaleForThisScreenSize(int width, int height) for (scale = 1; width / (scale + 1) >= 320 && height / (scale + 1) >= 240; ++scale) { } - return scale; + return 1.0f / scale; } #endif @@ -1153,11 +1208,6 @@ bool Minecraft::pauseGame() { if (isGamePaused() || m_pScreen) return false; - if (!isOnline() || m_pLevel->m_players.size() == 1) - { - // Actually pause the game, because fuck bedrock edition - m_bIsGamePaused = true; - } m_pLevel->savePlayerData(); getScreenChooser()->pushPauseScreen(); diff --git a/source/client/app/NinecraftApp.cpp b/source/client/app/NinecraftApp.cpp index 1c7bd839c..f0c610914 100644 --- a/source/client/app/NinecraftApp.cpp +++ b/source/client/app/NinecraftApp.cpp @@ -102,7 +102,13 @@ void NinecraftApp::_initRenderMaterials() void NinecraftApp::_initInput() { m_bIsTouchscreen = platform()->isTouchscreen(); - getOptions()->m_bUseController.set(platform()->hasGamepad()); + + //If someone has a gamepad connected, certainly they want to use it + if (platform()->hasGamepad()) + IInputHolder::activeType = IInputHolder::CONTROLLER; + else if (platform()->isTouchscreen()) + IInputHolder::activeType = IInputHolder::TOUCHSCREEN; + getOptions()->loadControls(); _reloadInput(); } @@ -365,13 +371,10 @@ void NinecraftApp::update() Multitouch::commit(); - if (getOptions()->m_bUseController.get()) + GameControllerHandler* pControllerHandler = platform()->getGameControllerHandler(); + if (pControllerHandler) { - GameControllerHandler* pControllerHandler = platform()->getGameControllerHandler(); - if (pControllerHandler) - { - pControllerHandler->refresh(); - } + pControllerHandler->refresh(); } Minecraft::update(); diff --git a/source/client/gui/Gui.cpp b/source/client/gui/Gui.cpp index 38ccbf65c..944f4b1bf 100644 --- a/source/client/gui/Gui.cpp +++ b/source/client/gui/Gui.cpp @@ -366,11 +366,11 @@ void Gui::handleScrollWheel(bool down) m_pMinecraft->m_pLocalPlayer->m_pInventory->selectSlot(slot); } -void Gui::handleKeyPressed(int keyCode) +void Gui::handleControlPressed(const ControlBind& bind) { Options* options = m_pMinecraft->getOptions(); - if (options->isKey(KM_INVENTORY, keyCode)) + if (options->isControl(KM_INVENTORY, bind)) { if (m_pMinecraft->m_pGameMode->isSurvivalType()) m_pMinecraft->setScreen(new InventoryScreen(m_pMinecraft->m_pLocalPlayer)); @@ -379,8 +379,8 @@ void Gui::handleKeyPressed(int keyCode) return; } - bool slotL = options->isKey(KM_SLOT_L, keyCode); - bool slotR = options->isKey(KM_SLOT_R, keyCode); + bool slotL = options->isControl(KM_SLOT_L, bind); + bool slotR = options->isControl(KM_SLOT_R, bind); if (slotL || slotR) { int maxItems = getNumSlots() - 1; @@ -405,10 +405,10 @@ void Gui::handleKeyPressed(int keyCode) return; } - if (options->isKey(KM_CHAT, keyCode) || options->isKey(KM_CHAT_CMD, keyCode)) + if (options->isControl(KM_CHAT, bind) || options->isControl(KM_CHAT_CMD, bind)) { if (!m_pMinecraft->m_pScreen) - m_pMinecraft->setScreen(new ChatScreen(m_pMinecraft->getOptions()->isKey(KM_CHAT_CMD, keyCode))); + m_pMinecraft->setScreen(new ChatScreen(m_pMinecraft->getOptions()->isControl(KM_CHAT_CMD, bind))); } } diff --git a/source/client/gui/Gui.hpp b/source/client/gui/Gui.hpp index 9957d2f65..8d6167b34 100644 --- a/source/client/gui/Gui.hpp +++ b/source/client/gui/Gui.hpp @@ -65,7 +65,7 @@ class Gui : public GuiComponent bool isInside(int mx, int my); void handleClick(int id, int mx, int my); void handleScrollWheel(bool down); - void handleKeyPressed(int keyCode); + void handleControlPressed(const ControlBind&); void renderMessages(bool bShowAll); void renderHearts(bool topLeft); void renderArmor(bool topLeft); diff --git a/source/client/gui/GuiElement.cpp b/source/client/gui/GuiElement.cpp index 2ddae5136..67e2a20fd 100644 --- a/source/client/gui/GuiElement.cpp +++ b/source/client/gui/GuiElement.cpp @@ -63,7 +63,7 @@ bool GuiElement::areaNavigation(Minecraft* pMinecraft, AreaNavigation::Direction return false; } -void GuiElement::handleButtonPress(Minecraft* pMinecraft, int key) +void GuiElement::handleControlPress(Minecraft* pMinecraft, const ControlBind& key) { } diff --git a/source/client/gui/GuiElement.hpp b/source/client/gui/GuiElement.hpp index 8ac2bc45c..95072c66c 100644 --- a/source/client/gui/GuiElement.hpp +++ b/source/client/gui/GuiElement.hpp @@ -42,7 +42,7 @@ class GuiElement : public GuiComponent virtual bool pointerPressed(Minecraft* pMinecraft, const MenuPointer& pointer); virtual bool pointerReleased(Minecraft* pMinecraft, const MenuPointer& pointer); virtual bool areaNavigation(Minecraft* pMinecraft, AreaNavigation::Direction); - virtual void handleButtonPress(Minecraft* pMinecraft, int key); + virtual void handleControlPress(Minecraft* pMinecraft, const ControlBind& key); virtual void handleTextChar(Minecraft* pMinecraft, int chr); virtual void handleClipboardPaste(const std::string& content); virtual void handleScroll(float force); diff --git a/source/client/gui/Screen.cpp b/source/client/gui/Screen.cpp index 5c029da2b..83346e7a9 100644 --- a/source/client/gui/Screen.cpp +++ b/source/client/gui/Screen.cpp @@ -56,7 +56,7 @@ Screen::~Screen() m_elements.clear(); } -void Screen::controllerEvent(GameController::StickID stickID, double deltaTime) +void Screen::controllerStickEvent(GameController::StickID stickID, double deltaTime) { // @TODO: this probably shouldn't be here GameController::StickEvent event; @@ -139,10 +139,10 @@ void Screen::init(Minecraft* pMinecraft, int width, int height) m_pFont = pMinecraft->m_pFont; // Apply UI theme to current Screen based on user preference - UITheme userTheme = m_pMinecraft->getOptions()->getUiTheme(); + UITheme userTheme = pMinecraft->getOptions()->getUiTheme(); // We don't bother applying the console theme automatically for generic screens because this completely fucks scaling if (m_uiTheme == UI_UNIVERSAL || (m_uiTheme == UI_GENERIC && userTheme != UI_CONSOLE)) - m_uiTheme = m_pMinecraft->getOptions()->getUiTheme(); + m_uiTheme = userTheme; setSize(width, height); initMenuPointer(); @@ -150,44 +150,44 @@ void Screen::init(Minecraft* pMinecraft, int width, int height) m_bLastPointerPressedState = false; } -void Screen::keyPressed(int key) +void Screen::controlPressed(const ControlBind& bind) { Options& options = *m_pMinecraft->getOptions(); GuiElement* element = _getSelectedElement(); - if (options.isKey(KM_MENU_CANCEL, key)) + if (options.isControl(KM_MENU_CANCEL, bind)) { m_pMinecraft->handleBack(false); } - if (m_pMinecraft->getOptions()->isKey(KM_MENU_TAB_LEFT, key)) + if (options.isControl(KM_MENU_TAB_LEFT, bind)) { prevTab(); } - if (m_pMinecraft->getOptions()->isKey(KM_MENU_TAB_RIGHT, key)) + if (options.isControl(KM_MENU_TAB_RIGHT, bind)) { nextTab(); } if (doElementTabbing()) { - if (options.isKey(KM_MENU_DOWN, key)) + if (options.isControl(KM_MENU_DOWN, bind)) { _areaNavigation(AreaNavigation::DOWN); } - else if (options.isKey(KM_MENU_UP, key)) + else if (options.isControl(KM_MENU_UP, bind)) { _areaNavigation(AreaNavigation::UP); } - else if (options.isKey(KM_MENU_RIGHT, key)) + else if (options.isControl(KM_MENU_RIGHT, bind)) { _areaNavigation(AreaNavigation::RIGHT); } - else if (options.isKey(KM_MENU_LEFT, key)) + else if (options.isControl(KM_MENU_LEFT, bind)) { _areaNavigation(AreaNavigation::LEFT); } - else if (options.isKey(KM_MENU_OK, key)) + else if (options.isControl(KM_MENU_OK, bind)) { if (element && element->isEnabled()) { @@ -204,7 +204,7 @@ void Screen::keyPressed(int key) if (element && element->isEnabled()) { - element->handleButtonPress(m_pMinecraft, key); + element->handleControlPress(m_pMinecraft, bind); } } @@ -255,6 +255,11 @@ void Screen::handleKeyboardClosed() } } +bool Screen::isInvalid(Minecraft*) +{ + return false; +} + static const char* g_panoramaList[] = { "gui/background/panorama_0.png", @@ -530,11 +535,14 @@ void Screen::selectElement(GuiElement* element) bool Screen::_areaNavigation(AreaNavigation::Direction dir) { - if (!m_pSelectedElement) return false; - - if (m_pSelectedElement->areaNavigation(m_pMinecraft, dir)) return true; + if (m_pSelectedElement && m_pSelectedElement->areaNavigation(m_pMinecraft, dir)) return true; - if (selectElementById(Navigation(this).navigateCyclic(dir, m_pSelectedElement->m_xPos + m_pSelectedElement->m_width / 2, m_pSelectedElement->m_yPos + m_pSelectedElement->m_height / 2))) + if ((m_pSelectedElement && selectElementById(Navigation(this).navigateCyclic(dir, + m_pSelectedElement->m_xPos + m_pSelectedElement->m_width / 2, + m_pSelectedElement->m_yPos + m_pSelectedElement->m_height / 2))) || + (!m_pSelectedElement && selectElementById(Navigation(this).navigate(dir, + m_width / 2, + m_height / 2, true)))) { _playSelectSound(); return true; @@ -723,7 +731,14 @@ void Screen::updateEvents() if (_useController()) { checkForPointerEvent(MOUSE_BUTTON_LEFT); - controllerEvent(); + + while(GameControllerManager::next()) + controllerEvent(); + + _processControllerDirection(1); + _processControllerDirection(2); + + controllerStickEvent(2); } } @@ -758,15 +773,26 @@ void Screen::keyboardEvent() } if (Keyboard::getEventKeyState()) - keyPressed(Keyboard::getEventKey()); + controlPressed(ControlBind(Keyboard::getEventKey(), GameController::BUTTON_NONE)); } void Screen::controllerEvent() { - _processControllerDirection(1); - _processControllerDirection(2); + // Ugly hack x2 + if (!doElementTabbing()) + { + if (GameControllerManager::getEventButtonState() && m_pMinecraft->getOptions()->getControl(KM_MENU_OK).isButton(GameControllerManager::getEventButton())) + { + m_menuPointer.isPressed = true; + } + else + { + m_menuPointer.isPressed = false; + } + } - controllerEvent(2); + if (GameControllerManager::getEventButtonState()) + controlPressed(ControlBind(-1, GameControllerManager::getEventButton())); } void Screen::checkForPointerEvent(MouseButtonType button) diff --git a/source/client/gui/Screen.hpp b/source/client/gui/Screen.hpp index a936e10ed..1f243d542 100644 --- a/source/client/gui/Screen.hpp +++ b/source/client/gui/Screen.hpp @@ -76,7 +76,7 @@ class Screen : public GuiComponent int getYOffset(); unsigned int getCursorMoveThrottle() const { return 65; } bool doElementTabbing() const; - void controllerEvent(GameController::StickID stickId, double deltaTime = 0.0); + void controllerStickEvent(GameController::StickID stickId, double deltaTime = 0.0); protected: virtual bool _areaNavigation(AreaNavigation::Direction); @@ -117,13 +117,14 @@ class Screen : public GuiComponent virtual void onTextBoxUpdated(int id) {}; virtual void pointerPressed(const MenuPointer& pointer, MouseButtonType btn); virtual void pointerReleased(const MenuPointer& pointer, MouseButtonType btn); - virtual void keyPressed(int); + virtual void controlPressed(const ControlBind&); virtual void handleTextChar(char); virtual void keyboardTextPaste(const std::string& text); virtual float getScale(int width, int height); static float GetConsoleScale(int height); virtual void setTextboxText(const std::string& text); virtual void handleKeyboardClosed(); + virtual bool isInvalid(Minecraft*); // ported from 0.8 virtual void renderMenuBackground(float f); diff --git a/source/client/gui/ScreenChooser.cpp b/source/client/gui/ScreenChooser.cpp index d2620083f..f48be2e22 100644 --- a/source/client/gui/ScreenChooser.cpp +++ b/source/client/gui/ScreenChooser.cpp @@ -6,7 +6,6 @@ #include "screens/inventory/CraftingScreen.hpp" #include "screens/inventory/ChestScreen.hpp" #include "screens/OptionsScreen.hpp" -#include "screens/OptionsScreen_Console.hpp" #include "screens/CreateWorldScreen.hpp" #include "screens/ProgressScreen.hpp" #include "screens/CreditsScreen.hpp" diff --git a/source/client/gui/VerticalLayout.cpp b/source/client/gui/VerticalLayout.cpp index b85fc8847..d5e4795e1 100644 --- a/source/client/gui/VerticalLayout.cpp +++ b/source/client/gui/VerticalLayout.cpp @@ -26,6 +26,11 @@ GuiElement* VerticalLayout::getElement(ID index) const return nullptr; } +bool VerticalLayout::isLastIn(AreaNavigation::Direction dir) +{ + return m_pSelectedElement && Navigation(this).navigate(dir, m_pSelectedElement->m_xPos + m_pSelectedElement->m_width / 2, m_pSelectedElement->m_yPos + m_pSelectedElement->m_height / 2) < 0; +} + bool VerticalLayout::selectElementById(ID id, bool sound) { GuiElement* element = getElement(id); @@ -99,7 +104,7 @@ void VerticalLayout::organize() } if (isSelected() && !m_pSelectedElement && m_pScreen->_useController()) - selectElementById(0, false); + startNavigation(); } void VerticalLayout::clear() @@ -115,18 +120,24 @@ void VerticalLayout::clear() } } +void VerticalLayout::startNavigation() +{ + AreaNavigation::ID id = Navigation(this).navigate(AreaNavigation::DOWN, m_pScreen->m_width / 2, 0); + if (id >= 0) + selectElementById(m_scrollAmount + id); +} + bool VerticalLayout::areaNavigation(Minecraft* mc, AreaNavigation::Direction dir) { if (m_pSelectedElement && m_pSelectedElement->areaNavigation(mc, dir)) return true; if (dir == AreaNavigation::DOWN) { - GuiElement* element = m_pSelectedElement; - if (element && isBottomElement(*element)) + if (isLastIn(dir)) { - if (m_bCyclic && !m_bCanScrollDown && m_scrollAmount > 0) + if (m_bCyclic && !m_bCanScrollDown) { - int x = element->m_xPos + element->m_width / 2; + int x = m_pSelectedElement->m_xPos + m_pSelectedElement->m_width / 2; updateScroll(0); AreaNavigation::ID id = Navigation(this).navigate(dir, x, 0, true); if (id >= 0) @@ -134,21 +145,28 @@ bool VerticalLayout::areaNavigation(Minecraft* mc, AreaNavigation::Direction dir return true; } - handleScroll(false); - areaNavigation(dir, element == getElement(ID(m_elements.size() - 1))); - return true; + if (m_bCanScrollDown) + { + GuiElement* oldElement = m_pSelectedElement; + while (oldElement == m_pSelectedElement) + { + handleScroll(false); + areaNavigation(dir, false); + } + + return true; + } } areaNavigation(dir); return true; } else if (dir == AreaNavigation::UP) { - GuiElement* element = m_pSelectedElement; - if (element && isTopElement(*element)) + if (isLastIn(dir)) { if (m_bCyclic && !m_scrollAmount) { - int x = element->m_xPos + element->m_width / 2; + int x = m_pSelectedElement->m_xPos + m_pSelectedElement->m_width / 2; while (m_bCanScrollDown) { updateScroll(m_scrollAmount + 1); @@ -189,7 +207,7 @@ void VerticalLayout::setSelected(bool b) GuiElement::setSelected(b); if (b && !m_pSelectedElement && m_pScreen->_useController()) - selectElementById(0, false); + startNavigation(); if (!b) selectElement(nullptr); @@ -284,5 +302,5 @@ bool VerticalLayout::Navigation::next(int& x, int& y, bool cycle) bool VerticalLayout::Navigation::isValid(ID id) { - return m_pLayout->m_pSelectedElement->getId() != (m_pLayout->m_scrollAmount + id); + return !m_pLayout->m_pSelectedElement || m_pLayout->m_pSelectedElement->getId() != (m_pLayout->m_scrollAmount + id); } \ No newline at end of file diff --git a/source/client/gui/VerticalLayout.hpp b/source/client/gui/VerticalLayout.hpp index d3dd64699..78d0673b5 100644 --- a/source/client/gui/VerticalLayout.hpp +++ b/source/client/gui/VerticalLayout.hpp @@ -12,6 +12,7 @@ class VerticalLayout : public GuiElement ~VerticalLayout(); GuiElement* getElement(ID) const; + bool isLastIn(AreaNavigation::Direction dir); bool isTopElement(GuiElement& element) const { return element.m_yPos == m_yPos; }; bool isBottomElement(GuiElement& element) const { return element.m_yPos == m_bottom; }; bool selectElementById(ID, bool sound = true); @@ -21,6 +22,7 @@ class VerticalLayout : public GuiElement void organize(); void clear(); + void startNavigation(); bool areaNavigation(Minecraft*, AreaNavigation::Direction) override; void areaNavigation(AreaNavigation::Direction, bool cyclic = false); void setSelected(bool); diff --git a/source/client/gui/components/OptionList.cpp b/source/client/gui/components/OptionList.cpp index 062f32f5e..fdbcfeebd 100644 --- a/source/client/gui/components/OptionList.cpp +++ b/source/client/gui/components/OptionList.cpp @@ -173,7 +173,8 @@ void OptionList::initControlsMenu() if (!m_pMinecraft->isTouchscreen()) m_items[idxSplit]->setEnabled(false); - m_items[idxController]->setEnabled(false); + if (!m_pMinecraft->platform()->hasGamepad()) + m_items[idxController]->setEnabled(false); } void OptionList::initVideoMenu() diff --git a/source/client/gui/components/TextBox.cpp b/source/client/gui/components/TextBox.cpp index f18371498..2351c501f 100644 --- a/source/client/gui/components/TextBox.cpp +++ b/source/client/gui/components/TextBox.cpp @@ -205,26 +205,26 @@ char TextBox::guessCharFromKey(int key) { #endif -void TextBox::handleButtonPress(Minecraft* pMinecraft, int key) +void TextBox::handleControlPress(Minecraft* pMinecraft, const ControlBind& bind) { Options& options = *pMinecraft->getOptions(); if (!hasFocus()) { - if (options.isKey(KM_MENU_OK, key)) + if (options.isControl(KM_MENU_OK, bind)) setFocused(true); return; } #ifndef HANDLE_CHARS_SEPARATELY - char guess = guessCharFromKey(key); + char guess = guessCharFromKey(bind.keyId); if (guess != '\0') { handleTextChar(guess); return; } #endif - switch (key) { + switch (bind.keyId) { case AKEYCODE_DEL: { // handled elsewhere, do not dupe diff --git a/source/client/gui/components/TextBox.hpp b/source/client/gui/components/TextBox.hpp index 59c02b0b1..ae2de1eec 100644 --- a/source/client/gui/components/TextBox.hpp +++ b/source/client/gui/components/TextBox.hpp @@ -40,7 +40,7 @@ class TextBox : public GuiElement public: void init(Font* pFont); bool pointerPressed(Minecraft* pMinecraft, const MenuPointer& pointer) override; - void handleButtonPress(Minecraft* pMinecraft, int key) override; + void handleControlPress(Minecraft* pMinecraft, const ControlBind&) override; void handleTextChar(Minecraft* pMinecraft, int chr) override; void handleClipboardPaste(const std::string& text) override; void render(Minecraft* pMinecraft, const MenuPointer& pointer) override; diff --git a/source/client/gui/screens/ChatScreen.cpp b/source/client/gui/screens/ChatScreen.cpp index 748b0aeac..042775d3e 100644 --- a/source/client/gui/screens/ChatScreen.cpp +++ b/source/client/gui/screens/ChatScreen.cpp @@ -58,15 +58,15 @@ void ChatScreen::render(float f) Screen::render(f); } -void ChatScreen::keyPressed(int keyCode) +void ChatScreen::controlPressed(const ControlBind& bind) { if (!_useController()) { - if (m_pMinecraft->getOptions()->isKey(KM_MENU_OK, keyCode)) + if (m_pMinecraft->getOptions()->isControl(KM_MENU_OK, bind)) sendMessageAndExit(); } - Screen::keyPressed(keyCode); + Screen::controlPressed(bind); } void ChatScreen::handleKeyboardClosed() @@ -77,6 +77,11 @@ void ChatScreen::handleKeyboardClosed() Screen::handleKeyboardClosed(); } +bool ChatScreen::isPauseScreen() +{ + return false; +} + void ChatScreen::sendMessageAndExit() { m_pMinecraft->sendMessage(m_textChat.getText()); diff --git a/source/client/gui/screens/ChatScreen.hpp b/source/client/gui/screens/ChatScreen.hpp index 2be599ab8..df2f8e56d 100644 --- a/source/client/gui/screens/ChatScreen.hpp +++ b/source/client/gui/screens/ChatScreen.hpp @@ -24,8 +24,9 @@ class ChatScreen : public Screen void init() override; void removed() override; void render(float f) override; - void keyPressed(int keyCode) override; + void controlPressed(const ControlBind& bind) override; void handleKeyboardClosed() override; + bool isPauseScreen() override; void sendMessageAndExit(); diff --git a/source/client/gui/screens/CreditsScreen.cpp b/source/client/gui/screens/CreditsScreen.cpp index b5bfb604d..a3afde9ea 100644 --- a/source/client/gui/screens/CreditsScreen.cpp +++ b/source/client/gui/screens/CreditsScreen.cpp @@ -53,9 +53,9 @@ bool CreditsScreen::isInGameScreen() return true; } -void CreditsScreen::keyPressed(int code) +void CreditsScreen::controlPressed(const ControlBind& bind) { - Screen::keyPressed(code); + Screen::controlPressed(bind); } void CreditsScreen::tick() diff --git a/source/client/gui/screens/CreditsScreen.hpp b/source/client/gui/screens/CreditsScreen.hpp index 27185894e..e922449fc 100644 --- a/source/client/gui/screens/CreditsScreen.hpp +++ b/source/client/gui/screens/CreditsScreen.hpp @@ -15,7 +15,7 @@ class CreditsScreen : public Screen public: void init() override; bool isInGameScreen() override; - void keyPressed(int code) override; + void controlPressed(const ControlBind&) override; void tick() override; void render(float f) override; bool handleBackEvent(bool b) override; diff --git a/source/client/gui/screens/IngameBlockSelectionScreen.cpp b/source/client/gui/screens/IngameBlockSelectionScreen.cpp index 1875b5ba9..27e7124ae 100644 --- a/source/client/gui/screens/IngameBlockSelectionScreen.cpp +++ b/source/client/gui/screens/IngameBlockSelectionScreen.cpp @@ -337,18 +337,23 @@ void IngameBlockSelectionScreen::removed() m_pMinecraft->m_pGui->inventoryUpdated(); } -void IngameBlockSelectionScreen::keyPressed(int keyCode) +void IngameBlockSelectionScreen::controlPressed(const ControlBind& bind) { - if (!_useController() && m_pMinecraft->getOptions()->isKey(KM_INVENTORY, keyCode)) + if (!_useController() && m_pMinecraft->getOptions()->isControl(KM_INVENTORY, bind)) { m_pMinecraft->handleBack(false); } else { - Screen::keyPressed(keyCode); + Screen::controlPressed(bind); } } +bool IngameBlockSelectionScreen::isPauseScreen() +{ + return false; +} + void IngameBlockSelectionScreen::selectSlotAndClose() { Inventory* pInv = getInventory(); diff --git a/source/client/gui/screens/IngameBlockSelectionScreen.hpp b/source/client/gui/screens/IngameBlockSelectionScreen.hpp index 097af0f64..45b14dcbc 100644 --- a/source/client/gui/screens/IngameBlockSelectionScreen.hpp +++ b/source/client/gui/screens/IngameBlockSelectionScreen.hpp @@ -40,7 +40,8 @@ class IngameBlockSelectionScreen : public Screen void pointerPressed(const MenuPointer& pointer, MouseButtonType btn) override; void pointerReleased(const MenuPointer& pointer, MouseButtonType btn) override; void removed() override; - void keyPressed(int key) override; + void controlPressed(const ControlBind&) override; + bool isPauseScreen() override; private: SlotID m_selectedSlot; diff --git a/source/client/gui/screens/OptionsScreen.cpp b/source/client/gui/screens/OptionsScreen.cpp index 2490863a9..d76d3544c 100644 --- a/source/client/gui/screens/OptionsScreen.cpp +++ b/source/client/gui/screens/OptionsScreen.cpp @@ -164,6 +164,16 @@ void OptionsScreen::handleScrollWheel(float force) m_pList->handleScrollWheel(force); } +bool OptionsScreen::isInvalid(Minecraft* mc) +{ + if (mc->getOptions()->getUiTheme() == UI_CONSOLE) + { + mc->getScreenChooser()->pushOptionsScreen(m_pParent); + return true; + } + return false; +} + #else #include "client/renderer/PatchManager.hpp" diff --git a/source/client/gui/screens/OptionsScreen.hpp b/source/client/gui/screens/OptionsScreen.hpp index 0100b20a9..c3e4f873c 100644 --- a/source/client/gui/screens/OptionsScreen.hpp +++ b/source/client/gui/screens/OptionsScreen.hpp @@ -42,6 +42,7 @@ class OptionsScreen : public Screen void _buttonClicked(Button* pButton) override; bool handleBackEvent(bool b) override; void handleScrollWheel(float force) override; + bool isInvalid(Minecraft*) override; private: void setCategory(OptionsCategory category); diff --git a/source/client/gui/screens/OptionsScreen_Console.cpp b/source/client/gui/screens/OptionsScreen_Console.cpp index 934283210..16037b173 100644 --- a/source/client/gui/screens/OptionsScreen_Console.cpp +++ b/source/client/gui/screens/OptionsScreen_Console.cpp @@ -35,7 +35,7 @@ void OptionsScreen_Console::_buttonClicked(Button* btn) void OptionsScreen_Console::init() { - Button* layoutButtons[] = {&m_btnHowToPlay, &m_btnControls, &m_btnSettings, &m_btnCredits, &m_btnResetToDefaults}; + Button* layoutButtons[] = { &m_btnHowToPlay, &m_btnControls, &m_btnSettings, &m_btnCredits, &m_btnResetToDefaults }; int buttonsWidth = 450; int buttonsHeight = 40; @@ -70,6 +70,16 @@ bool OptionsScreen_Console::handleBackEvent(bool b) return true; } +bool OptionsScreen_Console::isInvalid(Minecraft* mc) +{ + if (mc->getOptions()->getUiTheme() != UI_CONSOLE) + { + mc->getScreenChooser()->pushOptionsScreen(m_pParent); + return true; + } + return false; +} + #define HEADER(text) do { m_layout.m_elements.push_back(new OptionHeader_Console(text)); currentIndex++; } while (0) #define OPTION(name) do { options.name.addGuiElement(m_layout.m_elements, m_uiTheme); currentIndex++; } while (0) @@ -134,6 +144,7 @@ OptionHeader_Console::OptionHeader_Console(const std::string& text) : m_text(text) { m_height = 22; + setNavigable(false); } void OptionHeader_Console::render(Minecraft* pMinecraft, const MenuPointer& pointer) diff --git a/source/client/gui/screens/OptionsScreen_Console.hpp b/source/client/gui/screens/OptionsScreen_Console.hpp index 3a7a3cbe7..f8733cc0f 100644 --- a/source/client/gui/screens/OptionsScreen_Console.hpp +++ b/source/client/gui/screens/OptionsScreen_Console.hpp @@ -32,6 +32,7 @@ class OptionsScreen_Console : public Screen void init() override; void render(float) override; bool handleBackEvent(bool) override; + bool isInvalid(Minecraft*) override; private: Screen* m_pParent; diff --git a/source/client/gui/screens/PauseScreen.cpp b/source/client/gui/screens/PauseScreen.cpp index 0700e676c..e18752e77 100644 --- a/source/client/gui/screens/PauseScreen.cpp +++ b/source/client/gui/screens/PauseScreen.cpp @@ -119,3 +119,13 @@ void PauseScreen::_buttonClicked(Button* pButton) } #endif } + +bool PauseScreen::isInvalid(Minecraft* mc) +{ + if (mc->getOptions()->getUiTheme() == UI_CONSOLE) + { + mc->getScreenChooser()->pushPauseScreen(); + return true; + } + return false; +} diff --git a/source/client/gui/screens/PauseScreen.hpp b/source/client/gui/screens/PauseScreen.hpp index 80a94bee6..3fade2e3a 100644 --- a/source/client/gui/screens/PauseScreen.hpp +++ b/source/client/gui/screens/PauseScreen.hpp @@ -15,10 +15,11 @@ class PauseScreen : public Screen { public: PauseScreen(); - virtual void init() override; - virtual void tick() override; - virtual void render(float f) override; - virtual void _buttonClicked(Button*) override; + void init() override; + void tick() override; + void render(float f) override; + void _buttonClicked(Button*) override; + bool isInvalid(Minecraft*) override; void updateServerVisibilityText(); diff --git a/source/client/gui/screens/PauseScreen_Console.cpp b/source/client/gui/screens/PauseScreen_Console.cpp index 9c20d057d..641a18d4d 100644 --- a/source/client/gui/screens/PauseScreen_Console.cpp +++ b/source/client/gui/screens/PauseScreen_Console.cpp @@ -54,4 +54,14 @@ void PauseScreen_Console::_buttonClicked(Button* btn) m_pMinecraft->m_pLevel->saveGame(); // Minecraft auto-saves automatically when we hit the pause screen else if (btn->getId() == m_btnExitGame.getId()) m_pMinecraft->leaveGame(false); -} \ No newline at end of file +} + +bool PauseScreen_Console::isInvalid(Minecraft* mc) +{ + if (mc->getOptions()->getUiTheme() != UI_CONSOLE) + { + mc->getScreenChooser()->pushPauseScreen(); + return true; + } + return false; +} diff --git a/source/client/gui/screens/PauseScreen_Console.hpp b/source/client/gui/screens/PauseScreen_Console.hpp index 018fef1e8..05318350e 100644 --- a/source/client/gui/screens/PauseScreen_Console.hpp +++ b/source/client/gui/screens/PauseScreen_Console.hpp @@ -10,6 +10,7 @@ class PauseScreen_Console : public Screen void init() override; void render(float) override; void _buttonClicked(Button*) override; + bool isInvalid(Minecraft*) override; private: Button m_btnResume; diff --git a/source/client/gui/screens/SelectWorldScreen.cpp b/source/client/gui/screens/SelectWorldScreen.cpp index 18c54f512..daf86b280 100644 --- a/source/client/gui/screens/SelectWorldScreen.cpp +++ b/source/client/gui/screens/SelectWorldScreen.cpp @@ -76,23 +76,24 @@ bool SelectWorldScreen::isInGameScreen() return true; } -void SelectWorldScreen::keyPressed(int code) +void SelectWorldScreen::controlPressed(const ControlBind& bind) { + Options& options = *m_pMinecraft->getOptions(); #ifndef ORIGINAL_CODE - if (m_pMinecraft->getOptions()->getKey(KM_MENU_OK) == code) + if (options.isControl(KM_MENU_OK, bind)) m_pWorldSelectionList->selectItem(m_pWorldSelectionList->getItemAtPosition(m_width / 2, m_height / 2), false); #endif if (m_btnWorld.isSelected()) { - if (m_pMinecraft->getOptions()->getKey(KM_LEFT) == code) + if (options.isControl(KM_LEFT, bind)) m_pWorldSelectionList->stepLeft(); - if (m_pMinecraft->getOptions()->getKey(KM_RIGHT) == code) + if (options.isControl(KM_RIGHT, bind)) m_pWorldSelectionList->stepRight(); } - Screen::keyPressed(code); + Screen::controlPressed(bind); } static char g_SelectWorldFilterArray[] = { '/','\n','\r','\x09','\0','\xC','`','?','*','\\','<','>','|','"',':'}; diff --git a/source/client/gui/screens/SelectWorldScreen.hpp b/source/client/gui/screens/SelectWorldScreen.hpp index 7d1937175..b0b722ffb 100644 --- a/source/client/gui/screens/SelectWorldScreen.hpp +++ b/source/client/gui/screens/SelectWorldScreen.hpp @@ -24,7 +24,7 @@ class SelectWorldScreen : public Screen public: void init() override; bool isInGameScreen() override; - void keyPressed(int code) override; + void controlPressed(const ControlBind&) override; void tick() override; void render(float f) override; bool handleBackEvent(bool b) override; diff --git a/source/client/gui/screens/StartMenuScreen.cpp b/source/client/gui/screens/StartMenuScreen.cpp index 4d2dc03ac..7e7ca77a6 100644 --- a/source/client/gui/screens/StartMenuScreen.cpp +++ b/source/client/gui/screens/StartMenuScreen.cpp @@ -238,4 +238,14 @@ bool StartMenuScreen::handleBackEvent(bool b) m_pMinecraft->quit(); } return true; -} \ No newline at end of file +} + +bool StartMenuScreen::isInvalid(Minecraft* mc) +{ + if (mc->getOptions()->getUiTheme() == UI_CONSOLE) + { + mc->getScreenChooser()->pushStartScreen(); + return true; + } + return false; +} diff --git a/source/client/gui/screens/StartMenuScreen.hpp b/source/client/gui/screens/StartMenuScreen.hpp index f924d935f..abe355603 100644 --- a/source/client/gui/screens/StartMenuScreen.hpp +++ b/source/client/gui/screens/StartMenuScreen.hpp @@ -33,6 +33,7 @@ class StartMenuScreen : public Screen void drawSplash(); bool handleBackEvent(bool b) override; + bool isInvalid(Minecraft*) override; protected: Button m_startButton; diff --git a/source/client/gui/screens/StartMenuScreen_Console.cpp b/source/client/gui/screens/StartMenuScreen_Console.cpp index f67c0e40d..6961b3495 100644 --- a/source/client/gui/screens/StartMenuScreen_Console.cpp +++ b/source/client/gui/screens/StartMenuScreen_Console.cpp @@ -72,4 +72,14 @@ void StartMenuScreen_Console::_buttonClicked(Button* btn) m_pMinecraft->getScreenChooser()->pushOptionsScreen(this); else if (btn->getId() == m_btnExitGame.getId()) m_pMinecraft->quit(); -} \ No newline at end of file +} + +bool StartMenuScreen_Console::isInvalid(Minecraft* mc) +{ + if (mc->getOptions()->getUiTheme() != UI_CONSOLE) + { + mc->getScreenChooser()->pushStartScreen(); + return true; + } + return false; +} diff --git a/source/client/gui/screens/StartMenuScreen_Console.hpp b/source/client/gui/screens/StartMenuScreen_Console.hpp index 715122f1f..774f306ba 100644 --- a/source/client/gui/screens/StartMenuScreen_Console.hpp +++ b/source/client/gui/screens/StartMenuScreen_Console.hpp @@ -10,6 +10,7 @@ class StartMenuScreen_Console : public Screen void init() override; void render(float) override; void _buttonClicked(Button*) override; + bool isInvalid(Minecraft*) override; private: Button m_btnPlayGame; diff --git a/source/client/gui/screens/inventory/ContainerScreen.cpp b/source/client/gui/screens/inventory/ContainerScreen.cpp index c751f60af..9713dccc6 100644 --- a/source/client/gui/screens/inventory/ContainerScreen.cpp +++ b/source/client/gui/screens/inventory/ContainerScreen.cpp @@ -212,16 +212,17 @@ void ContainerScreen::render(float partialTicks) if (!name.empty()) { int w = m_pFont->width(name); - int tx = m_menuPointer.x - m_leftPos + 12; - int ty = m_menuPointer.y - m_topPos - 12; if (m_uiTheme == UI_CONSOLE) { - blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::POINTER_TEXT_PANEL_SLICES, tx - 6, ty - 6, w * 2 + 12, 28, 8); - MatrixStack::Ref tooltipMatrix = MatrixStack::World.push(); - m_pFont->drawScalable(name, tx, ty, -1); + int tx = m_menuPointer.x - m_leftPos + 12; + int ty = m_menuPointer.y - m_topPos - 28; + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::POINTER_TEXT_PANEL_SLICES, tx - 6, ty - 10, w * 2 + 12, 33, 8); + m_pFont->drawScalableShadow(name, tx, ty, -1); } else { + int tx = m_menuPointer.x - m_leftPos + 12; + int ty = m_menuPointer.y - m_topPos - 12; fillGradient(tx - 3, ty - 3, tx + w + 3, ty + 8 + 3, 0xC0000000, 0xC0000000); m_pFont->drawShadow(name, tx, ty, -1); } @@ -285,33 +286,34 @@ void ContainerScreen::slotClicked(const MenuPointer& pointer, MouseButtonType bu slotClicked(pointer, button, m_pMinecraft->m_pPlatform->shiftPressed()); } -void ContainerScreen::keyPressed(int keyCode) +void ContainerScreen::controlPressed(const ControlBind& bind) { - if (!_useController() && m_pMinecraft->getOptions()->isKey(KM_INVENTORY, keyCode)) + Options& options = *m_pMinecraft->getOptions(); + if (!_useController() && options.isControl(KM_INVENTORY, bind)) { m_pMinecraft->handleBack(false); } - else if (m_pMinecraft->getOptions()->isKey(KM_CONTAINER_QUICKMOVE, keyCode) && _useController()) + else if (options.isControl(KM_CONTAINER_QUICKMOVE, bind) && _useController()) { slotClicked(m_menuPointer, MOUSE_BUTTON_LEFT, true); } - else if (m_pMinecraft->getOptions()->isKey(KM_CONTAINER_SPLIT, keyCode) && _useController()) + else if (options.isControl(KM_CONTAINER_SPLIT, bind) && _useController()) { slotClicked(m_menuPointer, MOUSE_BUTTON_RIGHT, false); } else { if (_useController() && - ((m_pMinecraft->getOptions()->isKey(KM_MENU_UP, keyCode) && _selectSlotInDirection(AreaNavigation::UP)) || - (m_pMinecraft->getOptions()->isKey(KM_MENU_DOWN, keyCode) && _selectSlotInDirection(AreaNavigation::DOWN)) || - (m_pMinecraft->getOptions()->isKey(KM_MENU_RIGHT, keyCode) && _selectSlotInDirection(AreaNavigation::RIGHT)) || - (m_pMinecraft->getOptions()->isKey(KM_MENU_LEFT, keyCode) && _selectSlotInDirection(AreaNavigation::LEFT)))) + ((options.isControl(KM_MENU_UP, bind) && _selectSlotInDirection(AreaNavigation::UP)) || + (options.isControl(KM_MENU_DOWN, bind) && _selectSlotInDirection(AreaNavigation::DOWN)) || + (options.isControl(KM_MENU_RIGHT, bind) && _selectSlotInDirection(AreaNavigation::RIGHT)) || + (options.isControl(KM_MENU_LEFT, bind) && _selectSlotInDirection(AreaNavigation::LEFT)))) { _playSelectSound(); return; } - Screen::keyPressed(keyCode); + Screen::controlPressed(bind); } } diff --git a/source/client/gui/screens/inventory/ContainerScreen.hpp b/source/client/gui/screens/inventory/ContainerScreen.hpp index 274120153..b8de9a5e1 100644 --- a/source/client/gui/screens/inventory/ContainerScreen.hpp +++ b/source/client/gui/screens/inventory/ContainerScreen.hpp @@ -65,7 +65,7 @@ class ContainerScreen : public Screen void pointerPressed(const MenuPointer& pointer, MouseButtonType button) override; void pointerReleased(const MenuPointer& pointer, MouseButtonType button) override; void handlePointerPressed(bool isPressed) override; - void keyPressed(int key) override; + void controlPressed(const ControlBind&) override; const SlotDisplay& getSlotDisplay(const Slot&) const; diff --git a/source/client/options/Options.cpp b/source/client/options/Options.cpp index 4aea60bbc..220961692 100644 --- a/source/client/options/Options.cpp +++ b/source/client/options/Options.cpp @@ -152,9 +152,9 @@ void Options::_load() { std::string key = strings[i], value = strings[i + 1]; - std::map::iterator opt = m_options.find(key); - if (opt != m_options.end()) - opt->second->load(value); + HashMap::Iterator it = m_options.find(key); + if (it != m_options.end()) + it.value()->load(value); else if (key == "misc_oldtitle") logo3d = !readBool(value); else if (key == "gfx_resourcepacks") @@ -404,11 +404,11 @@ std::vector Options::getOptionStrings() #define SO(optname, value) do { vec.push_back(optname); vec.push_back(value); } while (0) std::stringstream ss; - for (std::map::iterator it = m_options.begin(); it != m_options.end(); ++it) + for (HashMap::Iterator it = m_options.begin(); it != m_options.end(); ++it) { ss.str(""); - it->second->save(ss); - SO(it->first, ss.str()); + it.value()->save(ss); + SO(it.key(), ss.str()); } SO("gfx_resourcepacks", savePackArray(m_resourcePacks)); @@ -418,7 +418,7 @@ std::vector Options::getOptionStrings() void Options::loadControls() { // Win32 key codes are being used by default -#define KM(idx, name, code) m_keyMappings[idx] = KeyMapping(name, code) +#define KM(idx, name, code) m_controlMappings[idx] = ControlMapping(name, code) KM(KM_FORWARD, "key.forward", 'W'); KM(KM_LEFT, "key.left", 'A'); KM(KM_BACKWARD, "key.back", 'S'); @@ -465,7 +465,7 @@ void Options::loadControls() // @TODO: These should **really** not be defined in here. How about AppPlatform? -#define KM(idx,code) m_keyMappings[idx].value = code +#define KM(idx,code) m_controlMappings[idx].bind.keyId = code #ifdef USE_SDL KM(KM_FORWARD, SDLVK_w); KM(KM_LEFT, SDLVK_a); @@ -577,64 +577,37 @@ void Options::loadControls() #endif #undef KM - if (m_bUseController.get()) - { -#define KM(idx,code) m_keyMappings[idx].value = code -#ifdef USE_SDL - KM(KM_TOGGLEDEBUG, SDL_CONTROLLER_BUTTON_GUIDE); - KM(KM_JUMP, SDL_CONTROLLER_BUTTON_A); - KM(KM_MENU_UP, SDL_CONTROLLER_BUTTON_DPAD_UP); - KM(KM_MENU_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN); - KM(KM_MENU_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT); - KM(KM_MENU_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); - KM(KM_MENU_TAB_LEFT, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - KM(KM_MENU_TAB_RIGHT, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); - KM(KM_MENU_OK, SDL_CONTROLLER_BUTTON_A); - KM(KM_MENU_CANCEL, SDL_CONTROLLER_BUTTON_B); - KM(KM_DROP, SDL_CONTROLLER_BUTTON_B); - KM(KM_CHAT, SDL_CONTROLLER_BUTTON_BACK); - KM(KM_INVENTORY, SDL_CONTROLLER_BUTTON_Y); - KM(KM_SNEAK, SDL_CONTROLLER_BUTTON_RIGHTSTICK); - KM(KM_CONTAINER_QUICKMOVE, SDL_CONTROLLER_BUTTON_Y); - KM(KM_CONTAINER_SPLIT, SDL_CONTROLLER_BUTTON_X); - KM(KM_TOGGLE3RD, SDL_CONTROLLER_BUTTON_LEFTSTICK); - KM(KM_SLOT_L, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - KM(KM_SLOT_R, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); - KM(KM_FLY_UP, SDL_CONTROLLER_BUTTON_A); - KM(KM_FLY_DOWN, SDL_CONTROLLER_BUTTON_RIGHTSTICK); -#else - KM(KM_TOGGLEDEBUG, GameController::BUTTON_GUIDE); - KM(KM_JUMP, GameController::BUTTON_A); - KM(KM_MENU_UP, GameController::BUTTON_DPAD_UP); - KM(KM_MENU_DOWN, GameController::BUTTON_DPAD_DOWN); - KM(KM_MENU_LEFT, GameController::BUTTON_DPAD_LEFT); - KM(KM_MENU_RIGHT, GameController::BUTTON_DPAD_RIGHT); - KM(KM_MENU_TAB_LEFT, GameController::BUTTON_LEFTSHOULDER); - KM(KM_MENU_TAB_RIGHT, GameController::BUTTON_RIGHTSHOULDER); - KM(KM_MENU_OK, GameController::BUTTON_A); - KM(KM_MENU_CANCEL, GameController::BUTTON_B); - KM(KM_MENU_PAUSE, GameController::BUTTON_START); - KM(KM_DROP, GameController::BUTTON_B); - KM(KM_CHAT, GameController::BUTTON_BACK); - KM(KM_INVENTORY, GameController::BUTTON_Y); - KM(KM_SNEAK, GameController::BUTTON_RIGHTSTICK); - KM(KM_CONTAINER_QUICKMOVE, GameController::BUTTON_Y); - KM(KM_CONTAINER_SPLIT, GameController::BUTTON_X); - KM(KM_TOGGLE3RD, GameController::BUTTON_LEFTSTICK); - KM(KM_SLOT_L, GameController::BUTTON_LEFTSHOULDER); - KM(KM_SLOT_R, GameController::BUTTON_RIGHTSHOULDER); - KM(KM_FLY_UP, GameController::BUTTON_A); - KM(KM_FLY_DOWN, GameController::BUTTON_RIGHTSTICK); -#endif -#undef KM - } +#define BTN(idx,code) m_controlMappings[idx].bind.buttonId = code + BTN(KM_TOGGLEDEBUG, GameController::BUTTON_GUIDE); + BTN(KM_JUMP, GameController::BUTTON_A); + BTN(KM_MENU_UP, GameController::BUTTON_DPAD_UP); + BTN(KM_MENU_DOWN, GameController::BUTTON_DPAD_DOWN); + BTN(KM_MENU_LEFT, GameController::BUTTON_DPAD_LEFT); + BTN(KM_MENU_RIGHT, GameController::BUTTON_DPAD_RIGHT); + BTN(KM_MENU_TAB_LEFT, GameController::BUTTON_LEFTSHOULDER); + BTN(KM_MENU_TAB_RIGHT, GameController::BUTTON_RIGHTSHOULDER); + BTN(KM_MENU_OK, GameController::BUTTON_A); + BTN(KM_MENU_CANCEL, GameController::BUTTON_B); + BTN(KM_MENU_PAUSE, GameController::BUTTON_START); + BTN(KM_DROP, GameController::BUTTON_B); + BTN(KM_CHAT, GameController::BUTTON_BACK); + BTN(KM_INVENTORY, GameController::BUTTON_Y); + BTN(KM_SNEAK, GameController::BUTTON_RIGHTSTICK); + BTN(KM_CONTAINER_QUICKMOVE, GameController::BUTTON_Y); + BTN(KM_CONTAINER_SPLIT, GameController::BUTTON_X); + BTN(KM_TOGGLE3RD, GameController::BUTTON_LEFTSTICK); + BTN(KM_SLOT_L, GameController::BUTTON_LEFTSHOULDER); + BTN(KM_SLOT_R, GameController::BUTTON_RIGHTSHOULDER); + BTN(KM_FLY_UP, GameController::BUTTON_A); + BTN(KM_FLY_DOWN, GameController::BUTTON_RIGHTSTICK); +#undef BTN } void Options::reset() { - for (std::map::iterator it = m_options.begin(); it != m_options.end(); ++it) + for (HashMap::Iterator it = m_options.begin(); it != m_options.end(); ++it) { - it->second->reset(); + it.value()->reset(); } } diff --git a/source/client/options/Options.hpp b/source/client/options/Options.hpp index d82d9e9e5..7723e2182 100644 --- a/source/client/options/Options.hpp +++ b/source/client/options/Options.hpp @@ -15,10 +15,12 @@ #include #include +#include "common/utility/HashMap.hpp" #include "common/threading/AsyncTask.hpp" +#include "client/player/input/GameController.hpp" #include "client/resources/ResourcePackManager.hpp" -enum eKeyMappingIndex +enum eControlMappingIndex { KM_FORWARD, KM_LEFT, @@ -65,13 +67,44 @@ enum eKeyMappingIndex KM_COUNT }; -struct KeyMapping +struct ControlBind +{ + //@TODO: Replace this with an universal key + int keyId; + GameController::EngineButtonID buttonId; + + ControlBind() : keyId(-1), buttonId(GameController::BUTTON_NONE) {} + ControlBind(int key, GameController::EngineButtonID button) : keyId(key), buttonId(button) {} + + bool isKey(int key) const { return keyId >= 0 && key == keyId; } + bool isButton(GameController::EngineButtonID button) const { return buttonId > GameController::BUTTON_NONE && button == buttonId; } + bool operator==(const ControlBind& other) const + { + return isKey(other.keyId) || isButton(other.buttonId); + } +}; + +struct ControlMapping { std::string key; - int value; + ControlBind bind; + int timesPressed; - KeyMapping() : value(-1) {} // key is automatically clear when constructed - KeyMapping(const char* keyName, int keyCode) : key(keyName), value(keyCode) {} + ControlMapping() : timesPressed(0) {} // key is automatically clear when constructed + ControlMapping(const char* keyName, int keyCode) : key(keyName), timesPressed(0) + { + bind.keyId = keyCode; + } + + void pressed() { ++timesPressed; } + void reset() { timesPressed = 0; } + bool consume() + { + if (timesPressed == 0) return false; + + --timesPressed; + return true; + } }; enum UITheme @@ -330,8 +363,6 @@ class HUDSizeOption : public MinMaxOption class Options { -public: - struct KeyBind; private: static bool _hasResourcePack(const ResourcePack& pack, ResourcePackStack& packs); static void _tryAddResourcePack(const std::string& name, ResourcePackStack& packs); @@ -368,8 +399,12 @@ class Options const AsyncTask& save(); std::vector getOptionStrings(); - int getKey(eKeyMappingIndex idx) const { return m_keyMappings[idx].value; } - bool isKey(eKeyMappingIndex idx, int keyCode) const { return getKey(idx) == keyCode; } + int getKey(eControlMappingIndex idx) const { return m_controlMappings[idx].bind.keyId; } + bool isKey(eControlMappingIndex idx, int keyCode) const { return getKey(idx) == keyCode; } + + ControlMapping& getControlMapping(eControlMappingIndex idx) { return m_controlMappings[idx]; } + const ControlBind& getControl(eControlMappingIndex idx) const { return m_controlMappings[idx].bind; } + bool isControl(eControlMappingIndex idx, const ControlBind& bind) const { return m_controlMappings[idx].bind == bind; } void loadControls(); void reset(); @@ -380,10 +415,10 @@ class Options private: Minecraft* m_pMinecraft; - std::map m_options; + HashMap m_options; AsyncTask m_saveTask; std::string m_filePath; - KeyMapping m_keyMappings[KM_COUNT]; + ControlMapping m_controlMappings[KM_COUNT]; public: friend class BoolOption; diff --git a/source/client/player/input/ControllerMoveInput.cpp b/source/client/player/input/ControllerMoveInput.cpp index cf813abe8..2da8e9475 100644 --- a/source/client/player/input/ControllerMoveInput.cpp +++ b/source/client/player/input/ControllerMoveInput.cpp @@ -43,9 +43,15 @@ void ControllerMoveInput::tick(Player* player) IMoveInput::tick(player); } -void ControllerMoveInput::setKey(int eventKey, bool eventKeyState) +void ControllerMoveInput::setKey(eControlMappingIndex ctrl, bool eventKeyState) { - KeyboardInput::setKey(eventKey, eventKeyState); + if (ctrl == KM_SNEAK) + { + if (eventKeyState) + KeyboardInput::setKey(ctrl, m_keys[INPUT_SNEAK] ^ 1); + } + else + KeyboardInput::setKey(ctrl, eventKeyState); //this->m_culledEntities = m_pOptions[36] == eventKey && eventKeyState; //this->field_21 = m_pOptions[34] == eventKey && eventKeyState; } diff --git a/source/client/player/input/ControllerMoveInput.hpp b/source/client/player/input/ControllerMoveInput.hpp index bfdaa8369..62e073982 100644 --- a/source/client/player/input/ControllerMoveInput.hpp +++ b/source/client/player/input/ControllerMoveInput.hpp @@ -12,7 +12,7 @@ class ControllerMoveInput : public KeyboardInput ControllerMoveInput(Options *options); void tick(Player *player) override; - void setKey(int eventKey, bool eventKeyState) override; + void setKey(eControlMappingIndex, bool eventKeyState) override; void releaseAllKeys() override; }; diff --git a/source/client/player/input/CustomInputHolder.cpp b/source/client/player/input/CustomInputHolder.cpp index c4dacfd4a..8f3d78600 100644 --- a/source/client/player/input/CustomInputHolder.cpp +++ b/source/client/player/input/CustomInputHolder.cpp @@ -8,11 +8,18 @@ #include "CustomInputHolder.hpp" -CustomInputHolder::CustomInputHolder(IMoveInput* pMoveInput, ITurnInput* pTurnInput, IBuildInput* pBuildInput) +CustomInputHolder::CustomInputHolder(IMoveInput* pMoveInput, ITurnInput* pTurnInput, IBuildInput* pBuildInput, bool isController) : + m_bIsController(isController) { setInputs(pMoveInput, pTurnInput, pBuildInput); } +bool CustomInputHolder::allowsType(Type type) const +{ + if (m_bIsController) return type == CONTROLLER; + return IInputHolder::allowsType(type); +} + IMoveInput* CustomInputHolder::getMoveInput() { return m_pMoveInput; diff --git a/source/client/player/input/CustomInputHolder.hpp b/source/client/player/input/CustomInputHolder.hpp index 3f4d2cb49..af49844cf 100644 --- a/source/client/player/input/CustomInputHolder.hpp +++ b/source/client/player/input/CustomInputHolder.hpp @@ -13,8 +13,9 @@ class CustomInputHolder : public IInputHolder { public: - CustomInputHolder(IMoveInput*, ITurnInput*, IBuildInput*); + CustomInputHolder(IMoveInput*, ITurnInput*, IBuildInput*, bool isController = false); + bool allowsType(Type) const override; IMoveInput* getMoveInput() override; ITurnInput* getTurnInput() override; IBuildInput* getBuildInput() override; @@ -26,5 +27,6 @@ class CustomInputHolder : public IInputHolder IMoveInput* m_pMoveInput; ITurnInput* m_pTurnInput; IBuildInput* m_pBuildInput; + bool m_bIsController; }; diff --git a/source/client/player/input/GameController.hpp b/source/client/player/input/GameController.hpp index f65ccf4f7..127ad9677 100644 --- a/source/client/player/input/GameController.hpp +++ b/source/client/player/input/GameController.hpp @@ -29,6 +29,7 @@ class GameController }; enum EngineButtonID { + BUTTON_NONE = -1, BUTTON_A, BUTTON_B, BUTTON_X, diff --git a/source/client/player/input/GameControllerHandler.hpp b/source/client/player/input/GameControllerHandler.hpp index 9b9064a99..4dc1e53a3 100644 --- a/source/client/player/input/GameControllerHandler.hpp +++ b/source/client/player/input/GameControllerHandler.hpp @@ -1,7 +1,6 @@ #pragma once -#include - +#include "common/utility/HashMap.hpp" #include "client/app/AppPlatform.hpp" #include "world/phys/Vec2.hpp" #include "GameController.hpp" @@ -11,8 +10,8 @@ class GameControllerHandler { public: - typedef std::map ButtonIDMap; - typedef std::map ButtonStateLookup; + typedef HashMap ButtonIDMap; + typedef HashMap ButtonStateLookup; public: GameControllerHandler(); diff --git a/source/client/player/input/GameControllerManager.cpp b/source/client/player/input/GameControllerManager.cpp index 404e57f2b..b370fd6e0 100644 --- a/source/client/player/input/GameControllerManager.cpp +++ b/source/client/player/input/GameControllerManager.cpp @@ -9,6 +9,7 @@ #include #include "GameControllerManager.hpp" +#include "IInputHolder.hpp" const float GameControllerManager::DIRECTION_X_THRESHOLD = 0.3f; const float GameControllerManager::DIRECTION_Y_THRESHOLD = 0.3f; @@ -17,6 +18,9 @@ const float GameControllerManager::DIRECTION_Y_THRESHOLD = 0.3f; // 0.3051f float GameControllerManager::_deadzonesX[][2] = { DEADZONE(0.3f), DEADZONE(0.3f) }; // Java: { DEADZONE(0.15f), DEADZONE(0.20f) }; float GameControllerManager::_deadzonesY[][2] = { DEADZONE(0.3f), DEADZONE(0.3f) }; // Java: { DEADZONE(0.15f), DEADZONE(0.20f) }; +std::vector GameControllerManager::_inputs; +GameController::ButtonState GameControllerManager::_states[]; +size_t GameControllerManager::_index = -1; bool GameControllerManager::isTouchedValues[] = { false, false }; float GameControllerManager::stickValuesX[] = { 0.0f, 0.0f }; @@ -24,6 +28,55 @@ float GameControllerManager::stickValuesY[] = { 0.0f, 0.0f }; float GameControllerManager::triggerValues[] = { 0.0f, 0.0f }; bool GameControllerManager::inReset = true; +void GameControllerManager::feedButton(GameController::ButtonState state, GameController::EngineButtonID button) +{ + // Prevent Crashes + if (button >= GameController::BUTTON_MAX || button < 0) { + return; + } + + IInputHolder::activeType = IInputHolder::CONTROLLER; + + GameController::ButtonEvent event; + event.state = state; + event.id = button; + event.bAllowRemapping = false; + + _inputs.push_back(event); + + _states[button] = state; +} + +bool GameControllerManager::next() +{ + if ((size_t)_index + 1 >= _inputs.size()) + { + if (!_inputs.empty()) clear(); + return false; + } + + _index++; + return true; +} + +GameController::EngineButtonID GameControllerManager::getEventButton() +{ + return _inputs[_index].id; +} + +GameController::ButtonState GameControllerManager::getEventButtonState() +{ + return _inputs[_index].state; +} + +bool GameControllerManager::isButtonDown(GameController::EngineButtonID button) +{ + if (button < 0 || button >= GameController::BUTTON_MAX) + return false; + + return _states[button] == GameController::BTN_STATE_DOWN; +} + bool GameControllerManager::isValidStick(GameController::StickID stickId) { // We have 2 'sticks' on the Xperia Play @@ -63,6 +116,9 @@ void GameControllerManager::feedStickX(GameController::StickID stickId, bool tou stickValuesX[index] = x; // LCE has a deadzone of 20000, ~0.3f on 360 inReset = false; + + if (x) + IInputHolder::activeType = IInputHolder::CONTROLLER; } void GameControllerManager::feedStickY(GameController::StickID stickId, bool touched, float y) @@ -83,6 +139,9 @@ void GameControllerManager::feedStickY(GameController::StickID stickId, bool tou stickValuesY[index] = y; // LCE has a deadzone of 20000, ~0.3f on 360 inReset = false; + + if (y) + IInputHolder::activeType = IInputHolder::CONTROLLER; } void GameControllerManager::feedStick(GameController::StickID stickId, bool touched, float x, float y) @@ -192,8 +251,15 @@ float GameControllerManager::getPressure(int triggerNo) return isValidTrigger(triggerNo) ? triggerValues[triggerNo - 1] : 0; } +void GameControllerManager::clear() +{ + _index = -1; + _inputs.clear(); +} + void GameControllerManager::reset() { + clear(); feedStick(1, 0, 0.0f, 0.0f); feedStick(2, 0, 0.0f, 0.0f); feedTrigger(1, 0.0f); diff --git a/source/client/player/input/GameControllerManager.hpp b/source/client/player/input/GameControllerManager.hpp index 346aba1ea..38c1ee497 100644 --- a/source/client/player/input/GameControllerManager.hpp +++ b/source/client/player/input/GameControllerManager.hpp @@ -19,8 +19,16 @@ class GameControllerManager static const float DIRECTION_Y_THRESHOLD; static float _deadzonesX[2][2], _deadzonesY[2][2]; + static std::vector _inputs; + static GameController::ButtonState _states[GameController::BUTTON_MAX]; + static size_t _index; public: + static void feedButton(GameController::ButtonState, GameController::EngineButtonID); + static bool next(); + static GameController::EngineButtonID getEventButton(); + static GameController::ButtonState getEventButtonState(); + static bool isButtonDown(GameController::EngineButtonID); static bool isValidStick(GameController::StickID stickId); static float linearTransform(float, float, float, bool); // SDL2 feeds controller stick update events one axis at a time @@ -39,6 +47,7 @@ class GameControllerManager static bool isValidTrigger(int triggerNo); static void feedTrigger(int triggerNo, float x); static float getPressure(int triggerNo); + static void clear(); static void reset(); static bool isReset() { return inReset; } diff --git a/source/client/player/input/IInputHolder.cpp b/source/client/player/input/IInputHolder.cpp index 4d017b5d5..69f1a2d64 100644 --- a/source/client/player/input/IInputHolder.cpp +++ b/source/client/player/input/IInputHolder.cpp @@ -9,6 +9,8 @@ #include "IInputHolder.hpp" #include "Mouse.hpp" +IInputHolder::Type IInputHolder::activeType = KEYBOARD; + IInputHolder::IInputHolder() : m_feedbackX(0), m_feedbackY(0) @@ -32,3 +34,8 @@ void IInputHolder::setScreenSize(int width, int height) getTurnInput()->setScreenSize(width, height); getBuildInput()->setScreenSize(width, height); } + +bool IInputHolder::allowsType(Type type) const +{ + return type == KEYBOARD || type == MOUSE; +} diff --git a/source/client/player/input/IInputHolder.hpp b/source/client/player/input/IInputHolder.hpp index 233d97dce..0aa9448c3 100644 --- a/source/client/player/input/IInputHolder.hpp +++ b/source/client/player/input/IInputHolder.hpp @@ -15,10 +15,19 @@ class IInputHolder { public: + enum Type + { + KEYBOARD, + MOUSE, + CONTROLLER, + TOUCHSCREEN + }; + IInputHolder(); virtual ~IInputHolder(); virtual bool allowPicking(); virtual void setScreenSize(int width, int height); + virtual bool allowsType(Type) const; virtual IMoveInput* getMoveInput() = 0; virtual ITurnInput* getTurnInput() = 0; virtual IBuildInput* getBuildInput() = 0; @@ -30,5 +39,9 @@ class IInputHolder float m_feedbackX; float m_feedbackY; float m_feedbackAlpha; + +public: + static Type activeType; + static Type lastType; }; diff --git a/source/client/player/input/IMoveInput.cpp b/source/client/player/input/IMoveInput.cpp index 7b646287f..385213791 100644 --- a/source/client/player/input/IMoveInput.cpp +++ b/source/client/player/input/IMoveInput.cpp @@ -30,7 +30,7 @@ void IMoveInput::render(float f) { } -void IMoveInput::setKey(int eventKey, bool eventKeyState) +void IMoveInput::setKey(eControlMappingIndex, bool eventKeyState) { } diff --git a/source/client/player/input/IMoveInput.hpp b/source/client/player/input/IMoveInput.hpp index bcde29324..862b1cb56 100644 --- a/source/client/player/input/IMoveInput.hpp +++ b/source/client/player/input/IMoveInput.hpp @@ -10,6 +10,8 @@ #include "compat/LegacyCPP.hpp" +#include "client/options/Options.hpp" + class Player; enum @@ -32,7 +34,7 @@ class IMoveInput virtual void releaseAllKeys(); virtual void render(float f); - virtual void setKey(int eventKey, bool eventKeyState); + virtual void setKey(eControlMappingIndex, bool eventKeyState); virtual void setScreenSize(int width, int height); virtual void tick(Player*); diff --git a/source/client/player/input/Keyboard.cpp b/source/client/player/input/Keyboard.cpp index 562003650..2fefc279b 100644 --- a/source/client/player/input/Keyboard.cpp +++ b/source/client/player/input/Keyboard.cpp @@ -8,6 +8,7 @@ #include #include "Keyboard.hpp" +#include "IInputHolder.hpp" #include "GameMods.hpp" @@ -22,6 +23,8 @@ void Keyboard::feed(KeyState state, int key) return; } + IInputHolder::activeType = IInputHolder::KEYBOARD; + _inputs.push_back(KeyboardAction(key, state)); _states[key] = state; @@ -30,7 +33,10 @@ void Keyboard::feed(KeyState state, int key) bool Keyboard::next() { if ((size_t)_index + 1 >= _inputs.size()) + { + if (!_inputs.empty()) reset(); return false; + } _index++; return true; diff --git a/source/client/player/input/KeyboardInput.cpp b/source/client/player/input/KeyboardInput.cpp index 739a8106f..5d6343ac6 100644 --- a/source/client/player/input/KeyboardInput.cpp +++ b/source/client/player/input/KeyboardInput.cpp @@ -29,19 +29,33 @@ void KeyboardInput::releaseAllKeys() m_keys[i] = false; } -void KeyboardInput::setKey(int eventKey, bool eventKeyState) +void KeyboardInput::setKey(eControlMappingIndex ctrl, bool eventKeyState) { - int index = -1; - - if (m_pOptions->getKey(KM_FORWARD) == eventKey) index = INPUT_FORWARD; - else if (m_pOptions->getKey(KM_BACKWARD) == eventKey) index = INPUT_BACKWARD; - else if (m_pOptions->getKey(KM_LEFT) == eventKey) index = INPUT_LEFT; - else if (m_pOptions->getKey(KM_RIGHT) == eventKey) index = INPUT_RIGHT; - else if (m_pOptions->getKey(KM_JUMP) == eventKey) index = INPUT_JUMP; - else if (m_pOptions->getKey(KM_SNEAK) == eventKey) index = INPUT_SNEAK; - - if (index == -1) + int index; + switch (ctrl) + { + case KM_FORWARD: + index = INPUT_FORWARD; + break; + case KM_BACKWARD: + index = INPUT_BACKWARD; + break; + case KM_LEFT: + index = INPUT_LEFT; + break; + case KM_RIGHT: + index = INPUT_RIGHT; + break; + case KM_JUMP: + index = INPUT_JUMP; + break; + case KM_SNEAK: + index = INPUT_SNEAK; + break; + default: + index = -1; return; + } m_keys[index] = eventKeyState; } diff --git a/source/client/player/input/KeyboardInput.hpp b/source/client/player/input/KeyboardInput.hpp index 156af6b70..ae09499a4 100644 --- a/source/client/player/input/KeyboardInput.hpp +++ b/source/client/player/input/KeyboardInput.hpp @@ -20,7 +20,7 @@ class KeyboardInput : public IMoveInput KeyboardInput(Options*); void releaseAllKeys() override; - void setKey(int eventKey, bool eventKeyState) override; + void setKey(eControlMappingIndex, bool eventKeyState) override; void tick(Player*) override; public: diff --git a/source/client/player/input/MouseDevice.cpp b/source/client/player/input/MouseDevice.cpp index 393f7f214..450e451e6 100644 --- a/source/client/player/input/MouseDevice.cpp +++ b/source/client/player/input/MouseDevice.cpp @@ -8,6 +8,7 @@ #include #include "MouseDevice.hpp" +#include "IInputHolder.hpp" MouseDevice::MouseDevice() { @@ -24,7 +25,10 @@ MouseDevice::MouseDevice() void MouseDevice::feed(MouseButtonType buttonType, bool buttonState, int posX, int posY) { if (buttonType != MOUSE_BUTTON_NONE) + { _inputs.push_back(MouseAction(buttonType, buttonState, posX, posY, 0)); + IInputHolder::activeType = IInputHolder::MOUSE; + } // Make sure button type is valid if (buttonType < MOUSE_BUTTON_COUNT) @@ -53,7 +57,10 @@ short MouseDevice::getY() bool MouseDevice::next() { if ((size_t)_index + 1 >= _inputs.size()) + { + if (!_inputs.empty()) reset(); return false; + } _index++; return true; diff --git a/source/client/player/input/Multitouch.cpp b/source/client/player/input/Multitouch.cpp index 3ba22d8d3..81dd970e9 100644 --- a/source/client/player/input/Multitouch.cpp +++ b/source/client/player/input/Multitouch.cpp @@ -8,6 +8,7 @@ #include #include "Multitouch.hpp" +#include "IInputHolder.hpp" int Multitouch::_activePointerCount; int Multitouch::_activePointerList[MAX_TOUCHES]; @@ -50,6 +51,7 @@ void Multitouch::feed(MouseButtonType a1, bool a2, int a3, int a4, int fingerId) MouseDevice* pDevice = g(fingerId); pDevice->feed(a1, a2, a3, a4); + IInputHolder::activeType = IInputHolder::TOUCHSCREEN; if (a1 != MOUSE_BUTTON_NONE) { diff --git a/source/client/player/input/TouchInputHolder.cpp b/source/client/player/input/TouchInputHolder.cpp index 95f7873fe..06709abd8 100644 --- a/source/client/player/input/TouchInputHolder.cpp +++ b/source/client/player/input/TouchInputHolder.cpp @@ -39,6 +39,11 @@ bool TouchInputHolder::allowPicking() return false; } +bool TouchInputHolder::allowsType(Type type) const +{ + return type == TOUCHSCREEN; +} + IMoveInput* TouchInputHolder::getMoveInput() { return &m_touchScreenInput; diff --git a/source/client/player/input/TouchInputHolder.hpp b/source/client/player/input/TouchInputHolder.hpp index 36ba4944d..f3c383497 100644 --- a/source/client/player/input/TouchInputHolder.hpp +++ b/source/client/player/input/TouchInputHolder.hpp @@ -20,6 +20,7 @@ class TouchInputHolder : public IInputHolder public: TouchInputHolder(Minecraft*, Options*); bool allowPicking() override; + bool allowsType(Type) const override; IMoveInput* getMoveInput() override; ITurnInput* getTurnInput() override; IBuildInput* getBuildInput() override; diff --git a/source/client/player/input/TouchscreenInput_TestFps.cpp b/source/client/player/input/TouchscreenInput_TestFps.cpp index af67bd4f8..38f2d7bf7 100644 --- a/source/client/player/input/TouchscreenInput_TestFps.cpp +++ b/source/client/player/input/TouchscreenInput_TestFps.cpp @@ -48,7 +48,7 @@ void TouchscreenInput_TestFps::releaseAllKeys() field_6C[i] = false; } -void TouchscreenInput_TestFps::setKey(int eventKey, bool eventKeyState) +void TouchscreenInput_TestFps::setKey(eControlMappingIndex, bool eventKeyState) { } diff --git a/source/client/player/input/TouchscreenInput_TestFps.hpp b/source/client/player/input/TouchscreenInput_TestFps.hpp index 25ac08599..d19f93a98 100644 --- a/source/client/player/input/TouchscreenInput_TestFps.hpp +++ b/source/client/player/input/TouchscreenInput_TestFps.hpp @@ -24,7 +24,7 @@ class TouchscreenInput_TestFps : public IMoveInput, public GuiComponent // IMoveInput void releaseAllKeys() override; - void setKey(int eventKey, bool eventKeyState) override; + void setKey(eControlMappingIndex, bool eventKeyState) override; void setScreenSize(int width, int height) override; void tick(Player*) override; void render(float f) override; diff --git a/source/client/renderer/Font.cpp b/source/client/renderer/Font.cpp index 6ec81196f..da91b56bb 100644 --- a/source/client/renderer/Font.cpp +++ b/source/client/renderer/Font.cpp @@ -8,7 +8,6 @@ #include "Font.hpp" #include "client/renderer/renderer/RenderMaterialGroup.hpp" -#include "client/renderer/renderer/Tesselator.hpp" #include "renderer/ShaderConstants.hpp" #include "renderer/MatrixStack.hpp" #include @@ -64,6 +63,10 @@ void Font::init(Options* pOpts) m_charWidthInt[i] = widthMax + 2; m_charWidthFloat[i] = float (widthMax) + 2; + Tesselator& t = Tesselator::instance; + t.begin(4); + buildChar(i, 0, 0); + m_charMeshes[i] = t.end(); } } @@ -165,7 +168,49 @@ void Font::drawWordWrap(const std::vector& lines, int x, int y, con void Font::draw(const std::string& str, int x, int y, const Color& color, bool bShadow) { - drawSlow(str, x, y, color, bShadow); + if (str.empty()) return; + + if (bShadow) + { + currentShaderDarkColor = Color(0.25f, 0.25f, 0.25f); + } + else + { + currentShaderDarkColor = Color::WHITE; + } + + m_pTextures->loadAndBindTexture(m_fileName); + + Color finalColor = color; + // For hex colors which don't specify an alpha + if (finalColor.a == 0.0f) + finalColor.a = 1.0f; + + MatrixStack::Ref mtx = MatrixStack::World.push(); + mtx->translate(Vec3(x, y, 0.0f)); + + currentShaderColor = finalColor; + float xOff = 0.0f; + + for (size_t i = 0; i < str.size(); i++) + { + if (str[i] == '\n') + { + mtx->translate(Vec3(0.0f, 12.0f, 0.0f)); + xOff = 0.0f; + continue; + } + + uint8_t x = uint8_t(str[i]); + + MatrixStack::Ref xmtx = MatrixStack::World.push(); + xmtx->translate(Vec3(xOff, 0.0f, 0.0f)); + m_charMeshes[x].render(m_materials.ui_text); + + xOff += m_charWidthFloat[x]; + } + + currentShaderColor = Color::WHITE; } void Font::drawSlow(const std::string& str, int x, int y, const Color& color, bool bShadow) @@ -188,18 +233,13 @@ void Font::drawSlow(const std::string& str, int x, int y, const Color& color, bo if (finalColor.a == 0.0f) finalColor.a = 1.0f; -#ifndef FEATURE_GFX_SHADERS - finalColor *= currentShaderDarkColor; -#endif - MatrixStack::Ref mtx = MatrixStack::World.push(); mtx->translate(Vec3(x, y, 0.0f)); + currentShaderColor = finalColor; Tesselator& t = Tesselator::instance; t.begin(4 * str.size()); - t.color(finalColor); - float cXPos = 0.0f, cYPos = 0.0f; for (size_t i = 0; i < str.size(); i++) @@ -219,6 +259,8 @@ void Font::drawSlow(const std::string& str, int x, int y, const Color& color, bo } t.draw(m_materials.ui_text); + + currentShaderColor = Color::WHITE; } void Font::onGraphicsReset() diff --git a/source/client/renderer/Font.hpp b/source/client/renderer/Font.hpp index 92020c250..49cc1303b 100644 --- a/source/client/renderer/Font.hpp +++ b/source/client/renderer/Font.hpp @@ -11,6 +11,7 @@ #include "Textures.hpp" #include "client/options/Options.hpp" #include "renderer/MaterialPtr.hpp" +#include "client/renderer/renderer/Tesselator.hpp" class Font { @@ -49,6 +50,7 @@ class Font int field_0; int m_charWidthInt[256]; float m_charWidthFloat[256]; + mce::Mesh m_charMeshes[256]; // huge gap, don't know why it's there... std::string m_fileName; Options* m_pOptions; diff --git a/source/client/renderer/GameRenderer.cpp b/source/client/renderer/GameRenderer.cpp index d71fd3d4e..96d8b0280 100644 --- a/source/client/renderer/GameRenderer.cpp +++ b/source/client/renderer/GameRenderer.cpp @@ -657,7 +657,7 @@ void GameRenderer::render(const Timer& timer) { if (m_pMinecraft->m_pScreen) { - m_pMinecraft->m_pScreen->controllerEvent(1, timer.m_deltaTime); + m_pMinecraft->m_pScreen->controllerStickEvent(1, timer.m_deltaTime); } } else diff --git a/source/common/utility/HashMap.hpp b/source/common/utility/HashMap.hpp new file mode 100644 index 000000000..9759033f6 --- /dev/null +++ b/source/common/utility/HashMap.hpp @@ -0,0 +1,413 @@ +#pragma once + +#include +#include +#include +#include + +template +struct HashMapEntry +{ + TKey key; + TValue value; + bool bOccupied; + bool bDeleted; + + HashMapEntry() : bOccupied(false), bDeleted(false) {} +}; + +template +struct HashFunction +{ + size_t operator()(const TKey& key) const; +}; + +template<> +struct HashFunction +{ + size_t operator()(const int8_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const uint8_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const int16_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const uint16_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const int32_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const uint32_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const int64_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const uint64_t& key) const { return key; } +}; + +template<> +struct HashFunction +{ + size_t operator()(const std::string& key) const + { + size_t hash = 5381; + for (size_t i = 0; i < key.length(); i++) + hash = ((hash << 5) + hash) + key[i]; + return hash; + } +}; + +template<> +struct HashFunction +{ + size_t operator()(const char* key) const + { + size_t hash = 5381; + while (*key) + hash = ((hash << 5) + hash) + size_t(*key++); + return hash; + } +}; + +template > +class HashMap +{ +private: + size_t _findSlot(const TKey& key) const + { + size_t hash = m_HashFunc(key); + size_t slot = hash % capacity(); + size_t originalSlot = slot; + + while (m_entries[slot].bOccupied) + { + if (!m_entries[slot].bDeleted && _keysEqual(m_entries[slot].key, key)) + return slot; + + slot = (slot + 1) % capacity(); + + if (slot == originalSlot) + break; + } + + return capacity(); + } + + size_t _findSlotForInsert(const TKey& key) const + { + size_t hash = m_HashFunc(key); + size_t slot = hash % capacity(); + size_t firstDeleted = capacity(); + size_t originalSlot = slot; + + while (m_entries[slot].bOccupied) + { + if (m_entries[slot].bDeleted) + { + if (firstDeleted == capacity()) + firstDeleted = slot; + } + else if (_keysEqual(m_entries[slot].key, key)) + { + return slot; + } + + slot = (slot + 1) % capacity(); + + if (slot == originalSlot) + break; + } + + if (firstDeleted != capacity()) + return firstDeleted; + + return slot; + } + + void _resize(size_t newCapacity) + { + std::vector> oldEntries = m_entries; + + m_entries.clear(); + m_entries.resize(newCapacity); + m_size = 0; + + for (size_t i = 0; i < oldEntries.size(); i++) + { + if (oldEntries[i].bOccupied && !oldEntries[i].bDeleted) + insert(oldEntries[i].key, oldEntries[i].value); + } + } + + bool _keysEqual(const TKey& a, const TKey& b) const { return a == b; } + +public: + HashMap() : m_size(0) + { + _resize(DEFAULT_CAPACITY); + } + + HashMap(size_t initialCapacity) : + m_size(0) + { + _resize(initialCapacity); + } + + bool insert(const TKey& key, const TValue& value) + { + if ((m_size * 100) / capacity() >= MAX_LOAD_FACTOR_PERCENT) + _resize(capacity() * 2); + + size_t slot = _findSlotForInsert(key); + + if (m_entries[slot].bOccupied && !m_entries[slot].bDeleted) + { + m_entries[slot].value = value; + return false; + } + + m_entries[slot].key = key; + m_entries[slot].value = value; + m_entries[slot].bOccupied = true; + m_entries[slot].bDeleted = false; + m_size++; + + return true; + } + + bool remove(const TKey& key) + { + return erase(find(key)) != end(); + } + + TValue* get(const TKey& key) + { + if (m_size == 0) + return nullptr; + + size_t slot = _findSlot(key); + + if (slot == capacity()) + return nullptr; + + return &m_entries[slot].value; + } + + const TValue* get(const TKey& key) const + { + if (m_size == 0) + return nullptr; + + size_t slot = _findSlot(key); + + if (slot == capacity()) + return nullptr; + + return &m_entries[slot].value; + } + + TValue& operator[](const TKey& key) + { + TValue* pValue = get(key); + if (pValue) + return *pValue; + + insert(key, TValue()); + return *get(key); + } + + void clear() + { + for (size_t i = 0; i < capacity(); ++i) + { + m_entries[i] = HashMapEntry(); + } + m_size = 0; + } + + size_t size() const { return m_size; } + size_t capacity() const { return m_entries.size(); } + bool empty() const { return m_size == 0; } + + class Iterator + { + private: + void _findNextOccupied() + { + while (m_index < m_entries->size() && (!m_entries->at(m_index).bOccupied || m_entries->at(m_index).bDeleted)) + m_index++; + } + + public: + Iterator(std::vector>* entries, size_t index) : + m_entries(entries), + m_index(index) + { + if (m_index < m_entries->size() && (!m_entries->at(m_index).bOccupied || m_entries->at(m_index).bDeleted)) + _findNextOccupied(); + } + + Iterator& operator++() + { + m_index++; + _findNextOccupied(); + return *this; + } + + Iterator operator++(int) + { + Iterator it = *this; + ++(*this); + return it; + } + + bool operator==(const Iterator& other) const { return m_entries == other.m_entries && m_index == other.m_index; } + bool operator!=(const Iterator& other) const { return !(*this == other); } + + TKey& key() { return m_entries->at(m_index).key; } + TValue& value() { return m_entries->at(m_index).value; } + + private: + std::vector>* m_entries; + size_t m_index; + + friend class HashMap; + }; + + Iterator find(const TKey& key) + { + if (m_size == 0) + return end(); + + size_t slot = _findSlot(key); + + if (slot == capacity()) + return end(); + + return Iterator(&m_entries, slot); + } + + Iterator begin() { return Iterator(&m_entries, 0); } + Iterator end() { return Iterator(&m_entries, capacity()); } + + Iterator erase(Iterator it) + { + if (it == end()) + return it; + + size_t slot = it.m_index; + if (slot < capacity() && + m_entries[slot].bOccupied && + !m_entries[slot].bDeleted) + { + m_entries[slot] = HashMapEntry(); + m_entries[slot].bOccupied = true; + m_entries[slot].bDeleted = true; + m_size--; + } + + return ++it; + } + + Iterator erase(Iterator first, Iterator last) + { + while (first != last) + first = erase(first); + + return first; + } + + class ConstIterator + { + private: + void _findNextOccupied() + { + while (m_index < m_entries->size() && (!m_entries->at(m_index).bOccupied || m_entries->at(m_index).bDeleted)) + m_index++; + } + + public: + ConstIterator(const std::vector>* entries, size_t index) : + m_entries(entries), + m_index(index) + { + if (m_index < entries->size() && (!m_entries->at(m_index).bOccupied || m_entries->at(m_index).bDeleted)) + _findNextOccupied(); + } + + ConstIterator& operator++() + { + m_index++; + _findNextOccupied(); + return *this; + } + + ConstIterator operator++(int) + { + ConstIterator it = *this; + ++(*this); + return it; + } + + bool operator==(const ConstIterator& other) const { return m_entries == other.m_entries && m_index == other.m_index; } + bool operator!=(const ConstIterator& other) const { return !(*this == other); } + + const TKey& key() { return m_entries->at(m_index).key; } + const TValue& value() { return m_entries->at(m_index).value; } + + private: + const std::vector>* m_entries; + size_t m_index; + + friend class HashMap; + }; + + ConstIterator find(const TKey& key) const + { + if (m_size == 0) + return end(); + + size_t slot = _findSlot(key); + + if (slot == capacity()) + return end(); + + return ConstIterator(&m_entries, slot); + } + + ConstIterator begin() const { return ConstIterator(&m_entries, 0); } + ConstIterator end() const { return ConstIterator(&m_entries, capacity()); } + +private: + std::vector> m_entries; + size_t m_size; + THash m_HashFunc; + + static const size_t DEFAULT_CAPACITY = 16; + static const size_t MAX_LOAD_FACTOR_PERCENT = 75; +}; \ No newline at end of file diff --git a/source/nbt/CompoundTag.cpp b/source/nbt/CompoundTag.cpp index 398ae945b..970e94bcb 100644 --- a/source/nbt/CompoundTag.cpp +++ b/source/nbt/CompoundTag.cpp @@ -3,6 +3,7 @@ #include "CompoundTag.hpp" #include "common/Util.hpp" +#include "common/Logger.hpp" CompoundTag::CompoundTag() { @@ -11,9 +12,9 @@ CompoundTag::CompoundTag() void CompoundTag::write(IDataOutput& dos) const { - for (std::map::const_iterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::ConstIterator it = m_tags.begin(); it != m_tags.end(); it++) { - writeNamedTag(it->first, *it->second, dos); + writeNamedTag(it.key(), *it.value(), dos); } dos.writeInt8(TAG_TYPE_END); @@ -144,15 +145,15 @@ bool CompoundTag::contains(const std::string& name, Tag::Type type) const const Tag* CompoundTag::get(const std::string& name) const { - std::map::const_iterator it = m_tags.find(name); - if (it != m_tags.end()) return it->second; + NamedTagMap::ConstIterator it = m_tags.find(name); + if (it != m_tags.end()) return it.value(); return nullptr; } Tag* CompoundTag::get(const std::string& name) { - std::map::iterator it = m_tags.find(name); - if (it != m_tags.end()) return it->second; + NamedTagMap::Iterator it = m_tags.find(name); + if (it != m_tags.end()) return it.value(); return nullptr; } @@ -298,9 +299,9 @@ CompoundTag* CompoundTag::uniqueClone() const { CompoundTag* newTag = new CompoundTag(); - for (NamedTagMap::const_iterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::ConstIterator it = m_tags.begin(); it != m_tags.end(); it++) { - newTag->put(it->first, it->second->copy()); + newTag->put(it.key(), it.value()->copy()); } return newTag; @@ -308,12 +309,12 @@ CompoundTag* CompoundTag::uniqueClone() const bool CompoundTag::remove(const std::string& name) { - std::map::iterator it = m_tags.find(name); + NamedTagMap::Iterator it = m_tags.find(name); if (it == m_tags.end()) return false; - delete it->second; - m_tags.erase(it); + delete it.value(); + m_tags.remove(name); return true; } @@ -322,9 +323,9 @@ void CompoundTag::deleteChildren() { if (!m_bLeak) { - for (std::map::iterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::Iterator it = m_tags.begin(); it != m_tags.end(); it++) { - Tag* tag = it->second; + Tag* tag = it.value(); tag->deleteChildren(); delete tag; } @@ -338,17 +339,13 @@ bool CompoundTag::operator==(const Tag& other) const const CompoundTag& other2 = (const CompoundTag&)(other); if (getId() == other2.getId() && m_tags.size() == other2.m_tags.size()) { - for (std::map::const_iterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::ConstIterator it = m_tags.begin(); it != m_tags.end(); it++) { - std::pair pair = *it, pair2; - std::map::const_iterator it2 = other2.m_tags.find(pair.first); + NamedTagMap::ConstIterator it2 = other2.m_tags.find(it.key()); if (it2 == other2.m_tags.end()) return false; // Failed to find tag in other by name - pair2 = *it2; - Tag *tag = pair.second, *tag2 = pair2.second; - - if (tag != tag2) + if (it.value() != it2.value()) return false; } diff --git a/source/nbt/CompoundTag.hpp b/source/nbt/CompoundTag.hpp index 4ed865255..6b02c3165 100644 --- a/source/nbt/CompoundTag.hpp +++ b/source/nbt/CompoundTag.hpp @@ -14,11 +14,12 @@ #include "StringTag.hpp" #include "FloatTag.hpp" #include "DoubleTag.hpp" +#include "common/utility/HashMap.hpp" class CompoundTag : public Tag { public: - typedef std::map NamedTagMap; + typedef HashMap NamedTagMap; public: CompoundTag(); diff --git a/source/world/entity/Arrow.hpp b/source/world/entity/Arrow.hpp index 5a08fc1da..83b90f6ad 100644 --- a/source/world/entity/Arrow.hpp +++ b/source/world/entity/Arrow.hpp @@ -21,7 +21,7 @@ class Arrow : public Entity public: void shoot(float x, float y, float z, float speed, float r) { shoot(Vec3(x, y, z), speed, r); }; - void shoot(Vec3 pos, float speed, float r); + void shoot(Vec3, float speed, float r); void lerpMotion(float x, float y, float z) { lerpMotion(Vec3(x, y, z)); }; void lerpMotion(const Vec3& vel) override; diff --git a/source/world/entity/Skeleton.cpp b/source/world/entity/Skeleton.cpp index 84ce64d2d..5858a3eea 100644 --- a/source/world/entity/Skeleton.cpp +++ b/source/world/entity/Skeleton.cpp @@ -33,7 +33,7 @@ void Skeleton::checkHurtTarget(Entity* ent, float f) { Arrow* arrow = new Arrow(m_pLevel, this); arrow->m_pos.y += 1; - float var8 = ent->m_pos.y - 0.2f - arrow->m_pos.y; + float var8 = ent->m_pos.y + ent->getHeadHeight() - 0.2f - arrow->m_pos.y; float var10 = Mth::sqrt(delta_x * delta_x + delta_z * delta_z) * 0.2f; m_pLevel->playSound(this, "random.bow", 1.0f, 1.0f / (m_random.nextFloat() * 0.4f + 0.8f)); m_pLevel->addEntity(arrow); diff --git a/source/world/inventory/ContainerMenu.cpp b/source/world/inventory/ContainerMenu.cpp index 8c083c908..78efea533 100644 --- a/source/world/inventory/ContainerMenu.cpp +++ b/source/world/inventory/ContainerMenu.cpp @@ -258,7 +258,9 @@ ItemStack ContainerMenu::clicked(int slotIndex, MouseButtonType mouseButton, boo { if (carried.m_count <= slot->getMaxStackSize()) { - std::swap(carried, slotItem); + ItemStack oldSlotItem = slotItem; + slot->set(carried); + inv->setCarried(oldSlotItem); } } else if (slotItem.getId() == carried.getId()) diff --git a/source/world/item/ItemStack.cpp b/source/world/item/ItemStack.cpp index 0ced312cf..9a8cf079f 100644 --- a/source/world/item/ItemStack.cpp +++ b/source/world/item/ItemStack.cpp @@ -158,10 +158,10 @@ CompoundTag* ItemStack::getNetworkUserData() const { CompoundTag* userData = new CompoundTag(); CompoundTag::NamedTagMap& tags = m_userData->rawView(); - for (CompoundTag::NamedTagMap::iterator it = tags.begin(); it != tags.end(); it++) + for (CompoundTag::NamedTagMap::Iterator it = tags.begin(); it != tags.end(); it++) { - const std::string& name = it->first; - const Tag* tag = it->second; + const std::string& name = it.key(); + const Tag* tag = it.value(); if (!tag) continue; if (name == TAG_REPAIR_COST) diff --git a/source/world/level/Level.cpp b/source/world/level/Level.cpp index e91a3c8f2..e64885541 100644 --- a/source/world/level/Level.cpp +++ b/source/world/level/Level.cpp @@ -322,10 +322,10 @@ Entity* Level::getEntity(Entity::ID id) const unsigned int Level::getEntityCount(const EntityCategories& category) const { EntityCategories::CategoriesMask mask = category.getCategoryMask(); - std::map::const_iterator it = m_entityCountsByCategory.find(mask); + HashMap::ConstIterator it = m_entityCountsByCategory.find(mask); if (it == m_entityCountsByCategory.end()) return 0; - return it->second; + return it.value(); } const EntityVector* Level::getAllEntities() const diff --git a/source/world/level/Level.hpp b/source/world/level/Level.hpp index 993830cf6..998e28748 100644 --- a/source/world/level/Level.hpp +++ b/source/world/level/Level.hpp @@ -9,12 +9,12 @@ #pragma once #include -#include #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif #include +#include "common/utility/HashMap.hpp" #include "client/renderer/LightUpdate.hpp" #include "world/tile/Tile.hpp" #include "world/entity/Entity.hpp" @@ -236,6 +236,6 @@ class Level : public LevelSource PathFinder* m_pPathFinder; MobSpawner* m_pMobSpawner; - std::map m_entityCountsByCategory; + HashMap m_entityCountsByCategory; }; From a6ecfee0990776458c4cb193760f8a6d3b9cb2d4 Mon Sep 17 00:00:00 2001 From: Wilyicaro Date: Tue, 24 Feb 2026 04:17:54 -0300 Subject: [PATCH 2/6] ugly. --- source/common/utility/HashMap.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/common/utility/HashMap.hpp b/source/common/utility/HashMap.hpp index 9759033f6..fe18f1235 100644 --- a/source/common/utility/HashMap.hpp +++ b/source/common/utility/HashMap.hpp @@ -151,7 +151,7 @@ class HashMap void _resize(size_t newCapacity) { - std::vector> oldEntries = m_entries; + std::vector > oldEntries = m_entries; m_entries.clear(); m_entries.resize(newCapacity); @@ -264,7 +264,7 @@ class HashMap } public: - Iterator(std::vector>* entries, size_t index) : + Iterator(std::vector >* entries, size_t index) : m_entries(entries), m_index(index) { @@ -293,7 +293,7 @@ class HashMap TValue& value() { return m_entries->at(m_index).value; } private: - std::vector>* m_entries; + std::vector >* m_entries; size_t m_index; friend class HashMap; @@ -352,7 +352,7 @@ class HashMap } public: - ConstIterator(const std::vector>* entries, size_t index) : + ConstIterator(const std::vector >* entries, size_t index) : m_entries(entries), m_index(index) { @@ -381,7 +381,7 @@ class HashMap const TValue& value() { return m_entries->at(m_index).value; } private: - const std::vector>* m_entries; + const std::vector >* m_entries; size_t m_index; friend class HashMap; @@ -404,7 +404,7 @@ class HashMap ConstIterator end() const { return ConstIterator(&m_entries, capacity()); } private: - std::vector> m_entries; + std::vector > m_entries; size_t m_size; THash m_HashFunc; From d9ae022daa52f85f1b96690c5f4e5fc09fa8774b Mon Sep 17 00:00:00 2001 From: Wilyicaro Date: Tue, 24 Feb 2026 04:20:58 -0300 Subject: [PATCH 3/6] removed nullptr usage from HashMap --- source/common/utility/HashMap.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/common/utility/HashMap.hpp b/source/common/utility/HashMap.hpp index fe18f1235..6788d7790 100644 --- a/source/common/utility/HashMap.hpp +++ b/source/common/utility/HashMap.hpp @@ -208,12 +208,12 @@ class HashMap TValue* get(const TKey& key) { if (m_size == 0) - return nullptr; + return NULL; size_t slot = _findSlot(key); if (slot == capacity()) - return nullptr; + return NULL; return &m_entries[slot].value; } @@ -221,12 +221,12 @@ class HashMap const TValue* get(const TKey& key) const { if (m_size == 0) - return nullptr; + return NULL; size_t slot = _findSlot(key); if (slot == capacity()) - return nullptr; + return NULL; return &m_entries[slot].value; } From cf76139a8bb12382f1cfebf264361ace72a3dd1c Mon Sep 17 00:00:00 2001 From: Wilyicaro Date: Tue, 24 Feb 2026 18:25:27 -0300 Subject: [PATCH 4/6] -Now, HashMap has the same general interface semantics as `std::map` -Fixed tickbox translucency not working right anymore --- GameMods.hpp | 1 - .../xinput/GameControllerHandler_xinput.cpp | 2 +- platforms/sdl/base/AppPlatform_sdl.cpp | 70 ++++++---------- platforms/sdl/base/AppPlatform_sdl.hpp | 1 - source/client/app/Minecraft.cpp | 16 ++-- source/client/gui/Screen.cpp | 10 ++- source/client/gui/Screen.hpp | 11 ++- source/client/gui/components/TickBox.cpp | 11 +-- source/client/gui/screens/OptionsScreen.cpp | 10 --- source/client/gui/screens/OptionsScreen.hpp | 1 - .../gui/screens/OptionsScreen_Console.cpp | 6 +- .../gui/screens/OptionsScreen_Console.hpp | 2 +- .../gui/screens/PanelScreen_Console.cpp | 1 + source/client/gui/screens/PauseScreen.cpp | 6 +- source/client/gui/screens/PauseScreen.hpp | 2 +- .../gui/screens/PauseScreen_Console.cpp | 7 +- .../gui/screens/PauseScreen_Console.hpp | 2 +- source/client/gui/screens/StartMenuScreen.cpp | 6 +- source/client/gui/screens/StartMenuScreen.hpp | 2 +- .../gui/screens/StartMenuScreen_Console.cpp | 7 +- .../gui/screens/StartMenuScreen_Console.hpp | 2 +- .../gui/screens/inventory/ContainerScreen.cpp | 2 +- source/client/options/Options.cpp | 6 +- source/client/options/Options.hpp | 5 +- .../player/input/GameControllerManager.cpp | 4 +- source/client/player/input/KeyboardInput.cpp | 28 ++----- source/client/renderer/Font.cpp | 2 +- source/client/renderer/Font.hpp | 8 +- source/common/utility/HashMap.hpp | 81 ++++++++++--------- source/nbt/CompoundTag.cpp | 16 ++-- source/world/item/ItemStack.cpp | 2 +- source/world/level/Level.cpp | 2 +- 32 files changed, 147 insertions(+), 185 deletions(-) diff --git a/GameMods.hpp b/GameMods.hpp index f3b2234c9..af788fb83 100644 --- a/GameMods.hpp +++ b/GameMods.hpp @@ -39,7 +39,6 @@ #define ENH_USE_OWN_AO // Use own ambient occlusion engine - looks pretty much the same except it fixes the corners #define ENH_ADD_OPTIONS_PAUSE // Add an 'options' button in the pause menu #define ENH_ALLOW_SAND_GRAVITY // Allow sand to fall. -#define ENH_USE_GUI_SCALE_2 // Use a 2x GUI scale instead of 3x. Looks better on PC #define ENH_ALLOW_SCROLL_WHEEL // Allow use of the scroll wheel to change selected inventory slots #define ENH_3D_INVENTORY_TILES // Uses 3D rendered inventory tiles, use with ENH_SHADE_HELD_TILES to render correctly. #define ENH_MENU_BACKGROUND // Renders a spinning panorama (if it's available) in the background of the main menu diff --git a/platforms/input/xinput/GameControllerHandler_xinput.cpp b/platforms/input/xinput/GameControllerHandler_xinput.cpp index 8cc544280..ea7eb7e87 100644 --- a/platforms/input/xinput/GameControllerHandler_xinput.cpp +++ b/platforms/input/xinput/GameControllerHandler_xinput.cpp @@ -89,7 +89,7 @@ void GameControllerHandler_xinput::refresh() { XINPUT_STATE& inputState = m_inputStates.m_inputState[id]; bool joinGameAlreadyFired = false; - for (ButtonIDMap::Iterator it = m_buttonIdMap.begin(); it != m_buttonIdMap.end(); it++) + for (ButtonIDMap::iterator it = m_buttonIdMap.begin(); it != m_buttonIdMap.end(); it++) { _processButton(id, inputState, it.key(), it.value(), joinGameAlreadyFired); } diff --git a/platforms/sdl/base/AppPlatform_sdl.cpp b/platforms/sdl/base/AppPlatform_sdl.cpp index 3f586caae..43ffbd19a 100644 --- a/platforms/sdl/base/AppPlatform_sdl.cpp +++ b/platforms/sdl/base/AppPlatform_sdl.cpp @@ -312,7 +312,7 @@ void AppPlatform_sdl::handleKeyEvent(const SDL_Event& event) void AppPlatform_sdl::handleControllerButtonEvent(SDL_JoystickID controllerIndex, uint8_t button, uint8_t state) { // Normal Key Press - GameControllerManager::feedButton(state == SDL_PRESSED ? GameController::BTN_STATE_DOWN : GameController::BTN_STATE_UP, GetEngineButton(button)); + GameControllerManager::feedButton(state == SDL_PRESSED ? GameController::BTN_STATE_DOWN : GameController::BTN_STATE_UP, _getEngineButton(button)); } void AppPlatform_sdl::handleControllerAxisEvent(SDL_JoystickID controllerIndex, uint8_t axis, int16_t value) @@ -493,53 +493,31 @@ Keyboard::KeyState AppPlatform_sdl::GetKeyState(uint8_t state) } } -GameController::EngineButtonID AppPlatform_sdl::GetEngineButton(uint8_t button) +static GameController::EngineButtonID _getEngineButton(uint8_t button) { switch (button) { - case SDL_CONTROLLER_BUTTON_A: - return GameController::BUTTON_A; - case SDL_CONTROLLER_BUTTON_B: - return GameController::BUTTON_B; - case SDL_CONTROLLER_BUTTON_X: - return GameController::BUTTON_X; - case SDL_CONTROLLER_BUTTON_Y: - return GameController::BUTTON_Y; - case SDL_CONTROLLER_BUTTON_DPAD_UP: - return GameController::BUTTON_DPAD_UP; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: - return GameController::BUTTON_DPAD_DOWN; - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: - return GameController::BUTTON_DPAD_LEFT; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: - return GameController::BUTTON_DPAD_RIGHT; - case SDL_CONTROLLER_BUTTON_LEFTSTICK: - return GameController::BUTTON_LEFTSTICK; - case SDL_CONTROLLER_BUTTON_RIGHTSTICK: - return GameController::BUTTON_RIGHTSTICK; - case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: - return GameController::BUTTON_LEFTSHOULDER; - case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: - return GameController::BUTTON_RIGHTSHOULDER; - case SDL_CONTROLLER_BUTTON_BACK: - return GameController::BUTTON_BACK; - case SDL_CONTROLLER_BUTTON_START: - return GameController::BUTTON_START; - case SDL_CONTROLLER_BUTTON_GUIDE: - return GameController::BUTTON_GUIDE; - case SDL_CONTROLLER_BUTTON_MISC1: - return GameController::BUTTON_MISC1; - case SDL_CONTROLLER_BUTTON_PADDLE1: - return GameController::BUTTON_PADDLE1; - case SDL_CONTROLLER_BUTTON_PADDLE2: - return GameController::BUTTON_PADDLE2; - case SDL_CONTROLLER_BUTTON_PADDLE3: - return GameController::BUTTON_PADDLE3; - case SDL_CONTROLLER_BUTTON_PADDLE4: - return GameController::BUTTON_PADDLE4; - case SDL_CONTROLLER_BUTTON_TOUCHPAD: - return GameController::BUTTON_TOUCHPAD; - default: - return GameController::BUTTON_NONE; + case SDL_CONTROLLER_BUTTON_A: return GameController::BUTTON_A; + case SDL_CONTROLLER_BUTTON_B: return GameController::BUTTON_B; + case SDL_CONTROLLER_BUTTON_X: return GameController::BUTTON_X; + case SDL_CONTROLLER_BUTTON_Y: return GameController::BUTTON_Y; + case SDL_CONTROLLER_BUTTON_DPAD_UP: return GameController::BUTTON_DPAD_UP; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: return GameController::BUTTON_DPAD_DOWN; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: return GameController::BUTTON_DPAD_LEFT; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: return GameController::BUTTON_DPAD_RIGHT; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: return GameController::BUTTON_LEFTSTICK; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: return GameController::BUTTON_RIGHTSTICK; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: return GameController::BUTTON_LEFTSHOULDER; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: return GameController::BUTTON_RIGHTSHOULDER; + case SDL_CONTROLLER_BUTTON_BACK: return GameController::BUTTON_BACK; + case SDL_CONTROLLER_BUTTON_START: return GameController::BUTTON_START; + case SDL_CONTROLLER_BUTTON_GUIDE: return GameController::BUTTON_GUIDE; + case SDL_CONTROLLER_BUTTON_MISC1: return GameController::BUTTON_MISC1; + case SDL_CONTROLLER_BUTTON_PADDLE1: return GameController::BUTTON_PADDLE1; + case SDL_CONTROLLER_BUTTON_PADDLE2: return GameController::BUTTON_PADDLE2; + case SDL_CONTROLLER_BUTTON_PADDLE3: return GameController::BUTTON_PADDLE3; + case SDL_CONTROLLER_BUTTON_PADDLE4: return GameController::BUTTON_PADDLE4; + case SDL_CONTROLLER_BUTTON_TOUCHPAD: return GameController::BUTTON_TOUCHPAD; + default: return GameController::BUTTON_NONE; } } diff --git a/platforms/sdl/base/AppPlatform_sdl.hpp b/platforms/sdl/base/AppPlatform_sdl.hpp index 0bdf38fd9..9b6c8bfc2 100644 --- a/platforms/sdl/base/AppPlatform_sdl.hpp +++ b/platforms/sdl/base/AppPlatform_sdl.hpp @@ -73,7 +73,6 @@ class AppPlatform_sdl : public AppPlatform static MouseButtonType GetMouseButtonType(uint8_t button); static bool GetMouseButtonState(const SDL_Event& event); static Keyboard::KeyState GetKeyState(uint8_t state); - static GameController::EngineButtonID GetEngineButton(uint8_t button); protected: ImageData m_iconImage; diff --git a/source/client/app/Minecraft.cpp b/source/client/app/Minecraft.cpp index d1713f144..5c0616d83 100644 --- a/source/client/app/Minecraft.cpp +++ b/source/client/app/Minecraft.cpp @@ -286,7 +286,7 @@ void Minecraft::setScreen(Screen* pScreen) return; } - if (pScreen && (pScreen->isErrorScreen() || pScreen->isInvalid(this))) + if (pScreen && (pScreen->isErrorScreen() || !pScreen->validate(this))) { // not in original delete pScreen; @@ -571,7 +571,6 @@ void Minecraft::tickInput() while (GameControllerManager::next()) { - if (!useController()) continue; GameController::EngineButtonID button = GameControllerManager::getEventButton(); bool bPressed = GameControllerManager::getEventButtonState() == GameController::BTN_STATE_DOWN; @@ -619,7 +618,7 @@ void Minecraft::tickInput() continue; // @TODO: Replace with KeyboardBuildInput - if (!useController() && getTimeMs() - field_2B4 <= 200) + if (getTimeMs() - field_2B4 <= 200) { if (getOptions()->isKey(KM_DESTROY, keyCode) && bPressed) { @@ -897,7 +896,10 @@ void Minecraft::tick() } if (m_pScreen) + { + m_pScreen->validate(this); m_pScreen->tick(); + } Multitouch::reset(); @@ -1093,12 +1095,7 @@ float Minecraft::getBestScaleForThisScreenSize(int width, int height) else if (m_pOptions->getUiTheme() == UI_CONSOLE) return Screen::GetConsoleScale(height); -#if MC_PLATFORM_XBOX -#define USE_JAVA_SCREEN_SCALING -#endif -#ifdef USE_JAVA_SCREEN_SCALING - // @HACK: the scaling code for Java/Pocket Screens when using the Console theme is pretty broken - if (m_pOptions->getUiTheme() != UI_CONSOLE) + if (getUiTheme() == UI_JAVA) { int scale; for (scale = 1; width / (scale + 1) >= 320 && height / (scale + 1) >= 240; ++scale) @@ -1106,7 +1103,6 @@ float Minecraft::getBestScaleForThisScreenSize(int width, int height) } return 1.0f / scale; } -#endif if (height > 1800) return 1.0f / 8.0f; diff --git a/source/client/gui/Screen.cpp b/source/client/gui/Screen.cpp index 83346e7a9..6611bbab2 100644 --- a/source/client/gui/Screen.cpp +++ b/source/client/gui/Screen.cpp @@ -47,7 +47,9 @@ Screen::Screen() m_bRenderPointer = false; m_lastTimeMoved = 0; m_cursorTick = 0; - m_uiTheme = UI_GENERIC; + m_themeSelection = UI_GENERIC; + m_uiTheme = UI_POCKET; + m_bUniversalUiTheme = false; } Screen::~Screen() @@ -141,7 +143,7 @@ void Screen::init(Minecraft* pMinecraft, int width, int height) // Apply UI theme to current Screen based on user preference UITheme userTheme = pMinecraft->getOptions()->getUiTheme(); // We don't bother applying the console theme automatically for generic screens because this completely fucks scaling - if (m_uiTheme == UI_UNIVERSAL || (m_uiTheme == UI_GENERIC && userTheme != UI_CONSOLE)) + if (m_themeSelection == UI_UNIVERSAL || (m_themeSelection == UI_GENERIC && userTheme != UI_CONSOLE)) m_uiTheme = userTheme; setSize(width, height); @@ -255,9 +257,9 @@ void Screen::handleKeyboardClosed() } } -bool Screen::isInvalid(Minecraft*) +bool Screen::validate(Minecraft*) { - return false; + return true; } static const char* g_panoramaList[] = diff --git a/source/client/gui/Screen.hpp b/source/client/gui/Screen.hpp index 1f243d542..316d2d59b 100644 --- a/source/client/gui/Screen.hpp +++ b/source/client/gui/Screen.hpp @@ -124,7 +124,7 @@ class Screen : public GuiComponent static float GetConsoleScale(int height); virtual void setTextboxText(const std::string& text); virtual void handleKeyboardClosed(); - virtual bool isInvalid(Minecraft*); + virtual bool validate(Minecraft*); // ported from 0.8 virtual void renderMenuBackground(float f); @@ -153,16 +153,25 @@ class Screen : public GuiComponent Screen* m_pScreen; }; + enum ThemeSelection + { + UI_SPECIFIC, // The Screen handles a specific UI Theme + UI_GENERIC, // The Screen is a Java / Pocket mix + UI_UNIVERSAL // The Screen automatically handles all UI themes + }; + int m_width; int m_height; bool m_bPassEvents; //@NOTE: This should be enabled only if the the actual screen handles the deletion of the previous screen, otherwise, there will be a memory leak! bool m_bDeletePrevious; + bool m_bUniversalUiTheme; Minecraft* m_pMinecraft; GuiElementList m_elements; GuiElement* m_pSelectedElement; Font* m_pFont; GuiElement* m_pClickedElement; + ThemeSelection m_themeSelection; UITheme m_uiTheme; #ifndef ORIGINAL_CODE diff --git a/source/client/gui/components/TickBox.cpp b/source/client/gui/components/TickBox.cpp index 2bce1cf86..a4451515d 100644 --- a/source/client/gui/components/TickBox.cpp +++ b/source/client/gui/components/TickBox.cpp @@ -48,11 +48,9 @@ void TickBox::render(Minecraft* mc, const MenuPointer& pointer) if (!mc->m_pScreen->doElementTabbing()) setSelected(isHovered(mc, pointer)); - if (!isEnabled()) - currentShaderColor.a *= 0.5f; - Color unselectedColor = Color::TEXT_GREY; - unselectedColor.a = currentShaderColor.a; + if (!isEnabled()) + unselectedColor.a = 0.5f; mc->m_pFont->drawScalable( getMessage(), m_xPos + C_TICKBOX_SIZE + 5, @@ -64,7 +62,10 @@ void TickBox::render(Minecraft* mc, const MenuPointer& pointer) getMessage(), m_xPos + C_TICKBOX_SIZE + 4, m_yPos + m_height / 2 - 9, - Color(204, 196, 13, currentShaderColor.a)); + Color(204, 196, 13, unselectedColor.a)); + + if (!isEnabled()) + currentShaderColor.a *= 0.5f; blitSprite(*mc->m_pTextures, isSelected() ? "gui/console/Graphics/Tickbox_Over.png" : "gui/console/Graphics/Tickbox_Norm.png", m_xPos, m_yPos + (m_height - C_TICKBOX_SIZE) / 2, C_TICKBOX_SIZE, C_TICKBOX_SIZE, &m_materials.ui_textured_and_glcolor); diff --git a/source/client/gui/screens/OptionsScreen.cpp b/source/client/gui/screens/OptionsScreen.cpp index d76d3544c..2490863a9 100644 --- a/source/client/gui/screens/OptionsScreen.cpp +++ b/source/client/gui/screens/OptionsScreen.cpp @@ -164,16 +164,6 @@ void OptionsScreen::handleScrollWheel(float force) m_pList->handleScrollWheel(force); } -bool OptionsScreen::isInvalid(Minecraft* mc) -{ - if (mc->getOptions()->getUiTheme() == UI_CONSOLE) - { - mc->getScreenChooser()->pushOptionsScreen(m_pParent); - return true; - } - return false; -} - #else #include "client/renderer/PatchManager.hpp" diff --git a/source/client/gui/screens/OptionsScreen.hpp b/source/client/gui/screens/OptionsScreen.hpp index c3e4f873c..0100b20a9 100644 --- a/source/client/gui/screens/OptionsScreen.hpp +++ b/source/client/gui/screens/OptionsScreen.hpp @@ -42,7 +42,6 @@ class OptionsScreen : public Screen void _buttonClicked(Button* pButton) override; bool handleBackEvent(bool b) override; void handleScrollWheel(float force) override; - bool isInvalid(Minecraft*) override; private: void setCategory(OptionsCategory category); diff --git a/source/client/gui/screens/OptionsScreen_Console.cpp b/source/client/gui/screens/OptionsScreen_Console.cpp index 16037b173..b829f07e4 100644 --- a/source/client/gui/screens/OptionsScreen_Console.cpp +++ b/source/client/gui/screens/OptionsScreen_Console.cpp @@ -70,14 +70,14 @@ bool OptionsScreen_Console::handleBackEvent(bool b) return true; } -bool OptionsScreen_Console::isInvalid(Minecraft* mc) +bool OptionsScreen_Console::validate(Minecraft* mc) { if (mc->getOptions()->getUiTheme() != UI_CONSOLE) { mc->getScreenChooser()->pushOptionsScreen(m_pParent); - return true; + return false; } - return false; + return true; } #define HEADER(text) do { m_layout.m_elements.push_back(new OptionHeader_Console(text)); currentIndex++; } while (0) diff --git a/source/client/gui/screens/OptionsScreen_Console.hpp b/source/client/gui/screens/OptionsScreen_Console.hpp index f8733cc0f..52f4db0ee 100644 --- a/source/client/gui/screens/OptionsScreen_Console.hpp +++ b/source/client/gui/screens/OptionsScreen_Console.hpp @@ -32,7 +32,7 @@ class OptionsScreen_Console : public Screen void init() override; void render(float) override; bool handleBackEvent(bool) override; - bool isInvalid(Minecraft*) override; + bool validate(Minecraft*) override; private: Screen* m_pParent; diff --git a/source/client/gui/screens/PanelScreen_Console.cpp b/source/client/gui/screens/PanelScreen_Console.cpp index d70b231be..6be5760fc 100644 --- a/source/client/gui/screens/PanelScreen_Console.cpp +++ b/source/client/gui/screens/PanelScreen_Console.cpp @@ -6,6 +6,7 @@ PanelScreen_Console::PanelScreen_Console(Screen* parent) : m_pParent(parent) , m_layout(this) { + m_themeSelection = UI_SPECIFIC; m_uiTheme = UI_CONSOLE; m_bDeletePrevious = false; } diff --git a/source/client/gui/screens/PauseScreen.cpp b/source/client/gui/screens/PauseScreen.cpp index e18752e77..440ea537f 100644 --- a/source/client/gui/screens/PauseScreen.cpp +++ b/source/client/gui/screens/PauseScreen.cpp @@ -120,12 +120,12 @@ void PauseScreen::_buttonClicked(Button* pButton) #endif } -bool PauseScreen::isInvalid(Minecraft* mc) +bool PauseScreen::validate(Minecraft* mc) { if (mc->getOptions()->getUiTheme() == UI_CONSOLE) { mc->getScreenChooser()->pushPauseScreen(); - return true; + return false; } - return false; + return true; } diff --git a/source/client/gui/screens/PauseScreen.hpp b/source/client/gui/screens/PauseScreen.hpp index 3fade2e3a..8c69621a8 100644 --- a/source/client/gui/screens/PauseScreen.hpp +++ b/source/client/gui/screens/PauseScreen.hpp @@ -19,7 +19,7 @@ class PauseScreen : public Screen void tick() override; void render(float f) override; void _buttonClicked(Button*) override; - bool isInvalid(Minecraft*) override; + bool validate(Minecraft*) override; void updateServerVisibilityText(); diff --git a/source/client/gui/screens/PauseScreen_Console.cpp b/source/client/gui/screens/PauseScreen_Console.cpp index 641a18d4d..2e5380c1c 100644 --- a/source/client/gui/screens/PauseScreen_Console.cpp +++ b/source/client/gui/screens/PauseScreen_Console.cpp @@ -14,6 +14,7 @@ PauseScreen_Console::PauseScreen_Console() : m_btnLeaderboards.setEnabled(false); m_btnAchievements.setEnabled(false); + m_themeSelection = UI_SPECIFIC; m_uiTheme = UI_CONSOLE; } @@ -56,12 +57,12 @@ void PauseScreen_Console::_buttonClicked(Button* btn) m_pMinecraft->leaveGame(false); } -bool PauseScreen_Console::isInvalid(Minecraft* mc) +bool PauseScreen_Console::validate(Minecraft* mc) { if (mc->getOptions()->getUiTheme() != UI_CONSOLE) { mc->getScreenChooser()->pushPauseScreen(); - return true; + return false; } - return false; + return true; } diff --git a/source/client/gui/screens/PauseScreen_Console.hpp b/source/client/gui/screens/PauseScreen_Console.hpp index 05318350e..8243c5be9 100644 --- a/source/client/gui/screens/PauseScreen_Console.hpp +++ b/source/client/gui/screens/PauseScreen_Console.hpp @@ -10,7 +10,7 @@ class PauseScreen_Console : public Screen void init() override; void render(float) override; void _buttonClicked(Button*) override; - bool isInvalid(Minecraft*) override; + bool validate(Minecraft*) override; private: Button m_btnResume; diff --git a/source/client/gui/screens/StartMenuScreen.cpp b/source/client/gui/screens/StartMenuScreen.cpp index 7e7ca77a6..292a3ff9c 100644 --- a/source/client/gui/screens/StartMenuScreen.cpp +++ b/source/client/gui/screens/StartMenuScreen.cpp @@ -240,12 +240,12 @@ bool StartMenuScreen::handleBackEvent(bool b) return true; } -bool StartMenuScreen::isInvalid(Minecraft* mc) +bool StartMenuScreen::validate(Minecraft* mc) { if (mc->getOptions()->getUiTheme() == UI_CONSOLE) { mc->getScreenChooser()->pushStartScreen(); - return true; + return false; } - return false; + return true; } diff --git a/source/client/gui/screens/StartMenuScreen.hpp b/source/client/gui/screens/StartMenuScreen.hpp index abe355603..9a44c74d3 100644 --- a/source/client/gui/screens/StartMenuScreen.hpp +++ b/source/client/gui/screens/StartMenuScreen.hpp @@ -33,7 +33,7 @@ class StartMenuScreen : public Screen void drawSplash(); bool handleBackEvent(bool b) override; - bool isInvalid(Minecraft*) override; + bool validate(Minecraft*) override; protected: Button m_startButton; diff --git a/source/client/gui/screens/StartMenuScreen_Console.cpp b/source/client/gui/screens/StartMenuScreen_Console.cpp index 6961b3495..ce84afc66 100644 --- a/source/client/gui/screens/StartMenuScreen_Console.cpp +++ b/source/client/gui/screens/StartMenuScreen_Console.cpp @@ -17,6 +17,7 @@ StartMenuScreen_Console::StartMenuScreen_Console() : m_btnAchievements.setEnabled(false); m_btnDownload.setEnabled(false); + m_themeSelection = UI_SPECIFIC; m_uiTheme = UI_CONSOLE; m_splash = SplashManager::singleton().getSplash(); @@ -74,12 +75,12 @@ void StartMenuScreen_Console::_buttonClicked(Button* btn) m_pMinecraft->quit(); } -bool StartMenuScreen_Console::isInvalid(Minecraft* mc) +bool StartMenuScreen_Console::validate(Minecraft* mc) { if (mc->getOptions()->getUiTheme() != UI_CONSOLE) { mc->getScreenChooser()->pushStartScreen(); - return true; + return false; } - return false; + return true; } diff --git a/source/client/gui/screens/StartMenuScreen_Console.hpp b/source/client/gui/screens/StartMenuScreen_Console.hpp index 774f306ba..100472c68 100644 --- a/source/client/gui/screens/StartMenuScreen_Console.hpp +++ b/source/client/gui/screens/StartMenuScreen_Console.hpp @@ -10,7 +10,7 @@ class StartMenuScreen_Console : public Screen void init() override; void render(float) override; void _buttonClicked(Button*) override; - bool isInvalid(Minecraft*) override; + bool validate(Minecraft*) override; private: Button m_btnPlayGame; diff --git a/source/client/gui/screens/inventory/ContainerScreen.cpp b/source/client/gui/screens/inventory/ContainerScreen.cpp index 9713dccc6..77cde805a 100644 --- a/source/client/gui/screens/inventory/ContainerScreen.cpp +++ b/source/client/gui/screens/inventory/ContainerScreen.cpp @@ -13,7 +13,7 @@ ContainerScreen::ContainerScreen(ContainerMenu* menu) : m_topPos(0), m_timeSlotDragged(0) { - m_uiTheme = UI_UNIVERSAL; + m_themeSelection = UI_UNIVERSAL; m_bRenderPointer = true; } diff --git a/source/client/options/Options.cpp b/source/client/options/Options.cpp index 220961692..98ccf792b 100644 --- a/source/client/options/Options.cpp +++ b/source/client/options/Options.cpp @@ -152,7 +152,7 @@ void Options::_load() { std::string key = strings[i], value = strings[i + 1]; - HashMap::Iterator it = m_options.find(key); + HashMap::iterator it = m_options.find(key); if (it != m_options.end()) it.value()->load(value); else if (key == "misc_oldtitle") @@ -404,7 +404,7 @@ std::vector Options::getOptionStrings() #define SO(optname, value) do { vec.push_back(optname); vec.push_back(value); } while (0) std::stringstream ss; - for (HashMap::Iterator it = m_options.begin(); it != m_options.end(); ++it) + for (HashMap::iterator it = m_options.begin(); it != m_options.end(); ++it) { ss.str(""); it.value()->save(ss); @@ -605,7 +605,7 @@ void Options::loadControls() void Options::reset() { - for (HashMap::Iterator it = m_options.begin(); it != m_options.end(); ++it) + for (HashMap::iterator it = m_options.begin(); it != m_options.end(); ++it) { it.value()->reset(); } diff --git a/source/client/options/Options.hpp b/source/client/options/Options.hpp index 7be1de521..adeba0084 100644 --- a/source/client/options/Options.hpp +++ b/source/client/options/Options.hpp @@ -111,10 +111,7 @@ enum UITheme { UI_POCKET, UI_JAVA, - UI_CONSOLE, - - UI_GENERIC, // The Screen is a Java / Pocket mix - UI_UNIVERSAL // The Screen automatically handles all UI themes + UI_CONSOLE }; enum LogoType diff --git a/source/client/player/input/GameControllerManager.cpp b/source/client/player/input/GameControllerManager.cpp index b370fd6e0..6580508db 100644 --- a/source/client/player/input/GameControllerManager.cpp +++ b/source/client/player/input/GameControllerManager.cpp @@ -117,7 +117,7 @@ void GameControllerManager::feedStickX(GameController::StickID stickId, bool tou inReset = false; - if (x) + if (x != 0.0f) IInputHolder::activeType = IInputHolder::CONTROLLER; } @@ -140,7 +140,7 @@ void GameControllerManager::feedStickY(GameController::StickID stickId, bool tou inReset = false; - if (y) + if (y != 0.0f) IInputHolder::activeType = IInputHolder::CONTROLLER; } diff --git a/source/client/player/input/KeyboardInput.cpp b/source/client/player/input/KeyboardInput.cpp index 5d6343ac6..ff9bb2040 100644 --- a/source/client/player/input/KeyboardInput.cpp +++ b/source/client/player/input/KeyboardInput.cpp @@ -34,27 +34,13 @@ void KeyboardInput::setKey(eControlMappingIndex ctrl, bool eventKeyState) int index; switch (ctrl) { - case KM_FORWARD: - index = INPUT_FORWARD; - break; - case KM_BACKWARD: - index = INPUT_BACKWARD; - break; - case KM_LEFT: - index = INPUT_LEFT; - break; - case KM_RIGHT: - index = INPUT_RIGHT; - break; - case KM_JUMP: - index = INPUT_JUMP; - break; - case KM_SNEAK: - index = INPUT_SNEAK; - break; - default: - index = -1; - return; + case KM_FORWARD: index = INPUT_FORWARD; break; + case KM_BACKWARD: index = INPUT_BACKWARD; break; + case KM_LEFT: index = INPUT_LEFT; break; + case KM_RIGHT: index = INPUT_RIGHT; break; + case KM_JUMP: index = INPUT_JUMP; break; + case KM_SNEAK: index = INPUT_SNEAK; break; + default: index = -1; return; } m_keys[index] = eventKeyState; diff --git a/source/client/renderer/Font.cpp b/source/client/renderer/Font.cpp index da91b56bb..4712bf336 100644 --- a/source/client/renderer/Font.cpp +++ b/source/client/renderer/Font.cpp @@ -32,7 +32,7 @@ void Font::init(Options* pOpts) TextureData* pTexture = m_pTextures->getTextureData(m_fileName, true); if (!pTexture) return; - for (int i = 0; i < 256; i++) // character number + for (int i = 0; i < FONT_CHARS_AMOUNT; i++) // character number { // note: the 'widthMax' behavior is assumed. It might not be like that exactly int widthMax = 0; diff --git a/source/client/renderer/Font.hpp b/source/client/renderer/Font.hpp index 49cc1303b..7823b5233 100644 --- a/source/client/renderer/Font.hpp +++ b/source/client/renderer/Font.hpp @@ -13,6 +13,8 @@ #include "renderer/MaterialPtr.hpp" #include "client/renderer/renderer/Tesselator.hpp" +#define FONT_CHARS_AMOUNT (256) + class Font { protected: @@ -48,9 +50,9 @@ class Font private: int field_0; - int m_charWidthInt[256]; - float m_charWidthFloat[256]; - mce::Mesh m_charMeshes[256]; + int m_charWidthInt[FONT_CHARS_AMOUNT]; + float m_charWidthFloat[FONT_CHARS_AMOUNT]; + mce::Mesh m_charMeshes[FONT_CHARS_AMOUNT]; // huge gap, don't know why it's there... std::string m_fileName; Options* m_pOptions; diff --git a/source/common/utility/HashMap.hpp b/source/common/utility/HashMap.hpp index 6788d7790..b9ea7800e 100644 --- a/source/common/utility/HashMap.hpp +++ b/source/common/utility/HashMap.hpp @@ -3,13 +3,13 @@ #include #include #include +#include #include template struct HashMapEntry { - TKey key; - TValue value; + std::pair pair; bool bOccupied; bool bDeleted; @@ -106,7 +106,7 @@ class HashMap while (m_entries[slot].bOccupied) { - if (!m_entries[slot].bDeleted && _keysEqual(m_entries[slot].key, key)) + if (!m_entries[slot].bDeleted && _keysEqual(m_entries[slot].pair.first, key)) return slot; slot = (slot + 1) % capacity(); @@ -132,7 +132,7 @@ class HashMap if (firstDeleted == capacity()) firstDeleted = slot; } - else if (_keysEqual(m_entries[slot].key, key)) + else if (_keysEqual(m_entries[slot].pair.first, key)) { return slot; } @@ -160,7 +160,7 @@ class HashMap for (size_t i = 0; i < oldEntries.size(); i++) { if (oldEntries[i].bOccupied && !oldEntries[i].bDeleted) - insert(oldEntries[i].key, oldEntries[i].value); + insert(oldEntries[i].pair.first, oldEntries[i].pair.second); } } @@ -187,12 +187,12 @@ class HashMap if (m_entries[slot].bOccupied && !m_entries[slot].bDeleted) { - m_entries[slot].value = value; + m_entries[slot].pair.second = value; return false; } - m_entries[slot].key = key; - m_entries[slot].value = value; + m_entries[slot].pair.first = key; + m_entries[slot].pair.second = value; m_entries[slot].bOccupied = true; m_entries[slot].bDeleted = false; m_size++; @@ -215,7 +215,7 @@ class HashMap if (slot == capacity()) return NULL; - return &m_entries[slot].value; + return &m_entries[slot].pair.second; } const TValue* get(const TKey& key) const @@ -228,7 +228,7 @@ class HashMap if (slot == capacity()) return NULL; - return &m_entries[slot].value; + return &m_entries[slot].pair.second; } TValue& operator[](const TKey& key) @@ -254,7 +254,7 @@ class HashMap size_t capacity() const { return m_entries.size(); } bool empty() const { return m_size == 0; } - class Iterator + class iterator { private: void _findNextOccupied() @@ -264,7 +264,7 @@ class HashMap } public: - Iterator(std::vector >* entries, size_t index) : + iterator(std::vector >* entries, size_t index) : m_entries(entries), m_index(index) { @@ -272,25 +272,26 @@ class HashMap _findNextOccupied(); } - Iterator& operator++() + iterator& operator++() { m_index++; _findNextOccupied(); return *this; } - Iterator operator++(int) + iterator operator++(int) { - Iterator it = *this; + iterator it = *this; ++(*this); return it; } - bool operator==(const Iterator& other) const { return m_entries == other.m_entries && m_index == other.m_index; } - bool operator!=(const Iterator& other) const { return !(*this == other); } + bool operator==(const iterator& other) const { return m_entries == other.m_entries && m_index == other.m_index; } + bool operator!=(const iterator& other) const { return !(*this == other); } - TKey& key() { return m_entries->at(m_index).key; } - TValue& value() { return m_entries->at(m_index).value; } + TKey& key() { return m_entries->at(m_index).pair.first; } + TValue& value() { return m_entries->at(m_index).pair.second; } + std::pair* operator->() { return &m_entries->at(m_index); } private: std::vector >* m_entries; @@ -299,7 +300,7 @@ class HashMap friend class HashMap; }; - Iterator find(const TKey& key) + iterator find(const TKey& key) { if (m_size == 0) return end(); @@ -309,13 +310,13 @@ class HashMap if (slot == capacity()) return end(); - return Iterator(&m_entries, slot); + return iterator(&m_entries, slot); } - Iterator begin() { return Iterator(&m_entries, 0); } - Iterator end() { return Iterator(&m_entries, capacity()); } + iterator begin() { return iterator(&m_entries, 0); } + iterator end() { return iterator(&m_entries, capacity()); } - Iterator erase(Iterator it) + iterator erase(iterator it) { if (it == end()) return it; @@ -325,8 +326,7 @@ class HashMap m_entries[slot].bOccupied && !m_entries[slot].bDeleted) { - m_entries[slot] = HashMapEntry(); - m_entries[slot].bOccupied = true; + m_entries[slot].pair = std::pair(); m_entries[slot].bDeleted = true; m_size--; } @@ -334,7 +334,7 @@ class HashMap return ++it; } - Iterator erase(Iterator first, Iterator last) + iterator erase(iterator first, iterator last) { while (first != last) first = erase(first); @@ -342,7 +342,7 @@ class HashMap return first; } - class ConstIterator + class const_iterator { private: void _findNextOccupied() @@ -352,7 +352,7 @@ class HashMap } public: - ConstIterator(const std::vector >* entries, size_t index) : + const_iterator(const std::vector >* entries, size_t index) : m_entries(entries), m_index(index) { @@ -360,25 +360,26 @@ class HashMap _findNextOccupied(); } - ConstIterator& operator++() + const_iterator& operator++() { m_index++; _findNextOccupied(); return *this; } - ConstIterator operator++(int) + const_iterator operator++(int) { - ConstIterator it = *this; + const_iterator it = *this; ++(*this); return it; } - bool operator==(const ConstIterator& other) const { return m_entries == other.m_entries && m_index == other.m_index; } - bool operator!=(const ConstIterator& other) const { return !(*this == other); } + bool operator==(const const_iterator& other) const { return m_entries == other.m_entries && m_index == other.m_index; } + bool operator!=(const const_iterator& other) const { return !(*this == other); } - const TKey& key() { return m_entries->at(m_index).key; } - const TValue& value() { return m_entries->at(m_index).value; } + const TKey& key() { return m_entries->at(m_index).pair.first; } + const TValue& value() { return m_entries->at(m_index).pair.second; } + const std::pair* operator->() { return &m_entries->at(m_index); } private: const std::vector >* m_entries; @@ -387,7 +388,7 @@ class HashMap friend class HashMap; }; - ConstIterator find(const TKey& key) const + const_iterator find(const TKey& key) const { if (m_size == 0) return end(); @@ -397,11 +398,11 @@ class HashMap if (slot == capacity()) return end(); - return ConstIterator(&m_entries, slot); + return const_iterator(&m_entries, slot); } - ConstIterator begin() const { return ConstIterator(&m_entries, 0); } - ConstIterator end() const { return ConstIterator(&m_entries, capacity()); } + const_iterator begin() const { return const_iterator(&m_entries, 0); } + const_iterator end() const { return const_iterator(&m_entries, capacity()); } private: std::vector > m_entries; diff --git a/source/nbt/CompoundTag.cpp b/source/nbt/CompoundTag.cpp index 970e94bcb..74b50795d 100644 --- a/source/nbt/CompoundTag.cpp +++ b/source/nbt/CompoundTag.cpp @@ -12,7 +12,7 @@ CompoundTag::CompoundTag() void CompoundTag::write(IDataOutput& dos) const { - for (NamedTagMap::ConstIterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::const_iterator it = m_tags.begin(); it != m_tags.end(); it++) { writeNamedTag(it.key(), *it.value(), dos); } @@ -145,14 +145,14 @@ bool CompoundTag::contains(const std::string& name, Tag::Type type) const const Tag* CompoundTag::get(const std::string& name) const { - NamedTagMap::ConstIterator it = m_tags.find(name); + NamedTagMap::const_iterator it = m_tags.find(name); if (it != m_tags.end()) return it.value(); return nullptr; } Tag* CompoundTag::get(const std::string& name) { - NamedTagMap::Iterator it = m_tags.find(name); + NamedTagMap::iterator it = m_tags.find(name); if (it != m_tags.end()) return it.value(); return nullptr; } @@ -299,7 +299,7 @@ CompoundTag* CompoundTag::uniqueClone() const { CompoundTag* newTag = new CompoundTag(); - for (NamedTagMap::ConstIterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::const_iterator it = m_tags.begin(); it != m_tags.end(); it++) { newTag->put(it.key(), it.value()->copy()); } @@ -309,7 +309,7 @@ CompoundTag* CompoundTag::uniqueClone() const bool CompoundTag::remove(const std::string& name) { - NamedTagMap::Iterator it = m_tags.find(name); + NamedTagMap::iterator it = m_tags.find(name); if (it == m_tags.end()) return false; @@ -323,7 +323,7 @@ void CompoundTag::deleteChildren() { if (!m_bLeak) { - for (NamedTagMap::Iterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::iterator it = m_tags.begin(); it != m_tags.end(); it++) { Tag* tag = it.value(); tag->deleteChildren(); @@ -339,9 +339,9 @@ bool CompoundTag::operator==(const Tag& other) const const CompoundTag& other2 = (const CompoundTag&)(other); if (getId() == other2.getId() && m_tags.size() == other2.m_tags.size()) { - for (NamedTagMap::ConstIterator it = m_tags.begin(); it != m_tags.end(); it++) + for (NamedTagMap::const_iterator it = m_tags.begin(); it != m_tags.end(); it++) { - NamedTagMap::ConstIterator it2 = other2.m_tags.find(it.key()); + NamedTagMap::const_iterator it2 = other2.m_tags.find(it.key()); if (it2 == other2.m_tags.end()) return false; // Failed to find tag in other by name diff --git a/source/world/item/ItemStack.cpp b/source/world/item/ItemStack.cpp index 9a8cf079f..de3a56dd0 100644 --- a/source/world/item/ItemStack.cpp +++ b/source/world/item/ItemStack.cpp @@ -158,7 +158,7 @@ CompoundTag* ItemStack::getNetworkUserData() const { CompoundTag* userData = new CompoundTag(); CompoundTag::NamedTagMap& tags = m_userData->rawView(); - for (CompoundTag::NamedTagMap::Iterator it = tags.begin(); it != tags.end(); it++) + for (CompoundTag::NamedTagMap::iterator it = tags.begin(); it != tags.end(); it++) { const std::string& name = it.key(); const Tag* tag = it.value(); diff --git a/source/world/level/Level.cpp b/source/world/level/Level.cpp index e64885541..e68c42ece 100644 --- a/source/world/level/Level.cpp +++ b/source/world/level/Level.cpp @@ -322,7 +322,7 @@ Entity* Level::getEntity(Entity::ID id) const unsigned int Level::getEntityCount(const EntityCategories& category) const { EntityCategories::CategoriesMask mask = category.getCategoryMask(); - HashMap::ConstIterator it = m_entityCountsByCategory.find(mask); + HashMap::const_iterator it = m_entityCountsByCategory.find(mask); if (it == m_entityCountsByCategory.end()) return 0; return it.value(); From 6bcbbb7b65fddc35d10460c4ef1fab3a47bfa738 Mon Sep 17 00:00:00 2001 From: Wilyicaro Date: Tue, 24 Feb 2026 18:28:17 -0300 Subject: [PATCH 5/6] fixed pausing when the game isn't online --- source/client/app/Minecraft.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/client/app/Minecraft.cpp b/source/client/app/Minecraft.cpp index 5c0616d83..888bb09a9 100644 --- a/source/client/app/Minecraft.cpp +++ b/source/client/app/Minecraft.cpp @@ -904,7 +904,7 @@ void Minecraft::tick() Multitouch::reset(); // Actually pause the game, because fuck bedrock edition - m_bIsGamePaused = !isOnline() || (m_pLevel && m_pLevel->m_players.size() == 1 && m_pScreen && m_pScreen->isPauseScreen()); + m_bIsGamePaused = (!isOnline() || (m_pLevel && m_pLevel->m_players.size() == 1)) && (m_pScreen && m_pScreen->isPauseScreen()); } } From af832895ac480e0fedf63e16015899a21962656c Mon Sep 17 00:00:00 2001 From: Wilyicaro <81383021+Wilyicaro@users.noreply.github.com> Date: Tue, 24 Feb 2026 18:33:10 -0300 Subject: [PATCH 6/6] should work --- platforms/sdl/base/AppPlatform_sdl.cpp | 58 +++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/platforms/sdl/base/AppPlatform_sdl.cpp b/platforms/sdl/base/AppPlatform_sdl.cpp index 43ffbd19a..52ee56012 100644 --- a/platforms/sdl/base/AppPlatform_sdl.cpp +++ b/platforms/sdl/base/AppPlatform_sdl.cpp @@ -309,6 +309,35 @@ void AppPlatform_sdl::handleKeyEvent(const SDL_Event& event) return _handleKeyEvent(key, state); } +static GameController::EngineButtonID _getEngineButton(uint8_t button) +{ + switch (button) + { + case SDL_CONTROLLER_BUTTON_A: return GameController::BUTTON_A; + case SDL_CONTROLLER_BUTTON_B: return GameController::BUTTON_B; + case SDL_CONTROLLER_BUTTON_X: return GameController::BUTTON_X; + case SDL_CONTROLLER_BUTTON_Y: return GameController::BUTTON_Y; + case SDL_CONTROLLER_BUTTON_DPAD_UP: return GameController::BUTTON_DPAD_UP; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: return GameController::BUTTON_DPAD_DOWN; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: return GameController::BUTTON_DPAD_LEFT; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: return GameController::BUTTON_DPAD_RIGHT; + case SDL_CONTROLLER_BUTTON_LEFTSTICK: return GameController::BUTTON_LEFTSTICK; + case SDL_CONTROLLER_BUTTON_RIGHTSTICK: return GameController::BUTTON_RIGHTSTICK; + case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: return GameController::BUTTON_LEFTSHOULDER; + case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: return GameController::BUTTON_RIGHTSHOULDER; + case SDL_CONTROLLER_BUTTON_BACK: return GameController::BUTTON_BACK; + case SDL_CONTROLLER_BUTTON_START: return GameController::BUTTON_START; + case SDL_CONTROLLER_BUTTON_GUIDE: return GameController::BUTTON_GUIDE; + case SDL_CONTROLLER_BUTTON_MISC1: return GameController::BUTTON_MISC1; + case SDL_CONTROLLER_BUTTON_PADDLE1: return GameController::BUTTON_PADDLE1; + case SDL_CONTROLLER_BUTTON_PADDLE2: return GameController::BUTTON_PADDLE2; + case SDL_CONTROLLER_BUTTON_PADDLE3: return GameController::BUTTON_PADDLE3; + case SDL_CONTROLLER_BUTTON_PADDLE4: return GameController::BUTTON_PADDLE4; + case SDL_CONTROLLER_BUTTON_TOUCHPAD: return GameController::BUTTON_TOUCHPAD; + default: return GameController::BUTTON_NONE; + } +} + void AppPlatform_sdl::handleControllerButtonEvent(SDL_JoystickID controllerIndex, uint8_t button, uint8_t state) { // Normal Key Press @@ -492,32 +521,3 @@ Keyboard::KeyState AppPlatform_sdl::GetKeyState(uint8_t state) return Keyboard::DOWN; } } - -static GameController::EngineButtonID _getEngineButton(uint8_t button) -{ - switch (button) - { - case SDL_CONTROLLER_BUTTON_A: return GameController::BUTTON_A; - case SDL_CONTROLLER_BUTTON_B: return GameController::BUTTON_B; - case SDL_CONTROLLER_BUTTON_X: return GameController::BUTTON_X; - case SDL_CONTROLLER_BUTTON_Y: return GameController::BUTTON_Y; - case SDL_CONTROLLER_BUTTON_DPAD_UP: return GameController::BUTTON_DPAD_UP; - case SDL_CONTROLLER_BUTTON_DPAD_DOWN: return GameController::BUTTON_DPAD_DOWN; - case SDL_CONTROLLER_BUTTON_DPAD_LEFT: return GameController::BUTTON_DPAD_LEFT; - case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: return GameController::BUTTON_DPAD_RIGHT; - case SDL_CONTROLLER_BUTTON_LEFTSTICK: return GameController::BUTTON_LEFTSTICK; - case SDL_CONTROLLER_BUTTON_RIGHTSTICK: return GameController::BUTTON_RIGHTSTICK; - case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: return GameController::BUTTON_LEFTSHOULDER; - case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: return GameController::BUTTON_RIGHTSHOULDER; - case SDL_CONTROLLER_BUTTON_BACK: return GameController::BUTTON_BACK; - case SDL_CONTROLLER_BUTTON_START: return GameController::BUTTON_START; - case SDL_CONTROLLER_BUTTON_GUIDE: return GameController::BUTTON_GUIDE; - case SDL_CONTROLLER_BUTTON_MISC1: return GameController::BUTTON_MISC1; - case SDL_CONTROLLER_BUTTON_PADDLE1: return GameController::BUTTON_PADDLE1; - case SDL_CONTROLLER_BUTTON_PADDLE2: return GameController::BUTTON_PADDLE2; - case SDL_CONTROLLER_BUTTON_PADDLE3: return GameController::BUTTON_PADDLE3; - case SDL_CONTROLLER_BUTTON_PADDLE4: return GameController::BUTTON_PADDLE4; - case SDL_CONTROLLER_BUTTON_TOUCHPAD: return GameController::BUTTON_TOUCHPAD; - default: return GameController::BUTTON_NONE; - } -}