-
-
Save Kaloyan501/6d6abc33e84abca1432304b01a14d098 to your computer and use it in GitHub Desktop.
| #include "stdafx.h" | |
| #include <Windows64\4JLibs\inc\4J_Input.h> | |
| #include <Common\App_enums.h> | |
| #include <Windows.h> | |
| #include <iostream> | |
| #include <atomic> | |
| #include <chrono> | |
| #include <vector> | |
| #include <algorithm> | |
| C_4JInput InputManager; | |
| // --- MOUSE EMULATION (cursor sampling / recenter) --- | |
| namespace MouseEmu | |
| { | |
| static std::atomic<int> g_dx(0); | |
| static std::atomic<int> g_dy(0); | |
| static float g_cached_rx = 0.0f; | |
| static float g_cached_ry = 0.0f; | |
| static bool g_cache_valid = false; | |
| static DWORD g_last_poll = 0; | |
| static bool g_was_focused = false; | |
| static POINT g_center = {0,0}; | |
| static float g_sensitivity = 0.035f; | |
| static float g_deadzone = 0.02f; | |
| static float g_decayPerSecond = 16.0f; | |
| template<typename T> | |
| T Clamp(T val, T minVal, T maxVal) | |
| { | |
| if (val < minVal) return minVal; | |
| if (val > maxVal) return maxVal; | |
| return val; | |
| } | |
| static void SetupFocusState() | |
| { | |
| HWND hwnd = FindWindowA("MinecraftClass", NULL); | |
| if (!hwnd) return; | |
| RECT rc; | |
| if (!GetClientRect(hwnd, &rc)) return; | |
| POINT ul = { rc.left, rc.top }, lr = { rc.right, rc.bottom }; | |
| ClientToScreen(hwnd, &ul); | |
| ClientToScreen(hwnd, &lr); | |
| g_center.x = (ul.x + lr.x) / 2; | |
| g_center.y = (ul.y + lr.y) / 2; | |
| RECT clip = { ul.x, ul.y, lr.x, lr.y }; | |
| ClipCursor(&clip); | |
| SetCursorPos(g_center.x, g_center.y); | |
| ShowCursor(FALSE); | |
| } | |
| static void ClearFocusState() | |
| { | |
| ClipCursor(NULL); | |
| ShowCursor(TRUE); | |
| g_dx.store(0); | |
| g_dy.store(0); | |
| g_cached_rx = 0.0f; | |
| g_cached_ry = 0.0f; | |
| } | |
| void NewFrame() | |
| { | |
| g_cache_valid = false; | |
| bool focused = false; | |
| HWND hwnd = FindWindowA("MinecraftClass", NULL); | |
| if (hwnd && GetForegroundWindow() == hwnd) focused = true; | |
| if (focused && !g_was_focused) { | |
| SetupFocusState(); | |
| g_was_focused = true; | |
| g_last_poll = GetTickCount(); | |
| return; | |
| } | |
| if (!focused && g_was_focused) { | |
| ClearFocusState(); | |
| g_was_focused = false; | |
| return; | |
| } | |
| if (focused) { | |
| POINT p; | |
| if (GetCursorPos(&p)) { | |
| int dx = p.x - g_center.x; | |
| int dy = p.y - g_center.y; | |
| if (dx != 0 || dy != 0) { | |
| g_dx.fetch_add(dx); | |
| g_dy.fetch_add(dy); | |
| SetCursorPos(g_center.x, g_center.y); | |
| } | |
| } | |
| } else { | |
| g_dx.store(0); | |
| g_dy.store(0); | |
| } | |
| } | |
| void Poll() | |
| { | |
| DWORD now = GetTickCount(); | |
| float dt = 1.0f / 60.0f; | |
| if (g_last_poll != 0) { | |
| DWORD diff = now - g_last_poll; | |
| dt = diff / 1000.0f; | |
| if (dt <= 0.0f) dt = 1.0f / 60.0f; | |
| } | |
| g_last_poll = now; | |
| if (g_cache_valid) return; | |
| int dx = g_dx.exchange(0); | |
| int dy = g_dy.exchange(0); | |
| dx = Clamp(dx, -30, 30); | |
| dy = Clamp(dy, -30, 30); | |
| float raw_rx = dx * g_sensitivity; | |
| float raw_ry = -dy * g_sensitivity; | |
| raw_rx = Clamp(raw_rx, -1.0f, 1.0f); | |
| raw_ry = Clamp(raw_ry, -1.0f, 1.0f); | |
| float lerpFactor = 1.0f - (float)exp(-g_decayPerSecond * dt); | |
| g_cached_rx = g_cached_rx + (raw_rx - g_cached_rx) * lerpFactor; | |
| g_cached_ry = g_cached_ry + (raw_ry - g_cached_ry) * lerpFactor; | |
| //char buf[128]; | |
| //_snprintf_s(buf, sizeof(buf), _TRUNCATE, "MouseEmu: dx=%d dy=%d raw_rx=%.3f raw_ry=%.3f\n", dx, dy, raw_rx, raw_ry); | |
| //OutputDebugStringA(buf); | |
| g_cache_valid = true; | |
| } | |
| float GetRX() { Poll(); return g_cached_rx; } | |
| float GetRY() { Poll(); return g_cached_ry; } | |
| } | |
| bool IsWindowFocused() | |
| { | |
| HWND hwnd = FindWindowA("MinecraftClass", NULL); | |
| if (!hwnd) | |
| return false; | |
| return GetForegroundWindow() == hwnd; | |
| } | |
| void C_4JInput::Initialise(int iInputStateC, unsigned char ucMapC, unsigned char ucActionC, unsigned char ucMenuActionC) | |
| { | |
| } | |
| bool m_CurrentKeys[256] = {}; | |
| bool m_PreviousKeys[256] = {}; | |
| void C_4JInput::Tick(void) | |
| { | |
| MouseEmu::NewFrame(); | |
| for (int i = 0; i < 256; ++i) | |
| { | |
| m_PreviousKeys[i] = m_CurrentKeys[i]; | |
| m_CurrentKeys[i] = (GetAsyncKeyState(i) & 0x8000) != 0; | |
| } | |
| } | |
| void C_4JInput::SetDeadzoneAndMovementRange(unsigned int uiDeadzone, unsigned int uiMovementRangeMax) | |
| { | |
| } | |
| void C_4JInput::SetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction, unsigned int uiActionVal) | |
| { | |
| } | |
| unsigned int C_4JInput::GetGameJoypadMaps(unsigned char ucMap, unsigned char ucAction) | |
| { | |
| return 0; | |
| } | |
| void C_4JInput::SetJoypadMapVal(int iPad, unsigned char ucMap) | |
| { | |
| } | |
| unsigned char C_4JInput::GetJoypadMapVal(int iPad) | |
| { | |
| return 0; | |
| } | |
| void C_4JInput::SetJoypadSensitivity(int iPad, float fSensitivity) | |
| { | |
| } | |
| bool KeyDown(int key) { | |
| return (GetAsyncKeyState(key) & 0x8000) != 0; | |
| } | |
| bool KeyPressed(int key) { | |
| return m_CurrentKeys[key] && !m_PreviousKeys[key]; | |
| } | |
| bool KeyReleased(int key) { | |
| return !m_CurrentKeys[key] && m_PreviousKeys[key]; | |
| } | |
| bool C_4JInput::ButtonPressed(int iPad, unsigned char ucAction) | |
| { | |
| if (!IsWindowFocused()) | |
| return false; | |
| switch (ucAction) { | |
| //MAIN CONTROLS | |
| case ACTION_MENU_UP: return KeyPressed(VK_UP); | |
| case ACTION_MENU_DOWN: return KeyPressed(VK_DOWN); | |
| case ACTION_MENU_LEFT: return KeyPressed(VK_LEFT); | |
| case ACTION_MENU_RIGHT: return KeyPressed(VK_RIGHT); | |
| case ACTION_MENU_OK: | |
| case ACTION_MENU_A: return KeyPressed(VK_RETURN); | |
| case ACTION_MENU_CANCEL: | |
| case ACTION_MENU_B: return KeyPressed(VK_ESCAPE); | |
| case ACTION_MENU_X: return KeyPressed('R'); | |
| case ACTION_MENU_Y: return KeyPressed('T'); | |
| case MINECRAFT_ACTION_FORWARD: return KeyPressed('W'); | |
| case MINECRAFT_ACTION_BACKWARD: return KeyPressed('S'); | |
| case MINECRAFT_ACTION_LEFT: return KeyPressed('A'); | |
| case MINECRAFT_ACTION_RIGHT: return KeyPressed('D'); | |
| case MINECRAFT_ACTION_JUMP: return KeyPressed(VK_SPACE); | |
| case MINECRAFT_ACTION_INVENTORY: return KeyPressed('R'); | |
| case MINECRAFT_ACTION_DROP: return KeyPressed('Z'); | |
| case MINECRAFT_ACTION_ACTION: return KeyPressed(VK_LBUTTON); | |
| case MINECRAFT_ACTION_USE: return KeyPressed(VK_RBUTTON); | |
| //AUXILARY ACTIONS | |
| case MINECRAFT_ACTION_RENDER_THIRD_PERSON: return KeyPressed(VK_F5); | |
| case MINECRAFT_ACTION_PAUSEMENU: return KeyPressed(VK_ESCAPE); | |
| case MINECRAFT_ACTION_CRAFTING: return KeyPressed('T'); | |
| case MINECRAFT_ACTION_SNEAK_TOGGLE: return KeyPressed(VK_LSHIFT); | |
| //DPAD | |
| case MINECRAFT_ACTION_DPAD_UP: return KeyPressed('I'); | |
| case MINECRAFT_ACTION_DPAD_DOWN: return KeyPressed('K'); | |
| case MINECRAFT_ACTION_DPAD_LEFT: return KeyPressed('J'); | |
| case MINECRAFT_ACTION_DPAD_RIGHT: return KeyPressed('L'); | |
| case MINECRAFT_ACTION_LEFT_SCROLL: return KeyPressed('1'); | |
| case MINECRAFT_ACTION_RIGHT_SCROLL: return KeyPressed('2'); | |
| case ACTION_MENU_LEFT_SCROLL: return KeyPressed('Q'); | |
| case ACTION_MENU_RIGHT_SCROLL: return KeyPressed('E'); | |
| case ACTION_MENU_OTHER_STICK_PRESS: | |
| case ACTION_MENU_STICK_PRESS: return KeyPressed(VK_LCONTROL); | |
| } | |
| return false; | |
| } | |
| bool C_4JInput::ButtonReleased(int iPad, unsigned char ucAction) | |
| { | |
| if (!IsWindowFocused()) | |
| return false; | |
| switch (ucAction) { | |
| //MAIN CONTROLS | |
| case ACTION_MENU_UP: return KeyReleased(VK_UP); | |
| case ACTION_MENU_DOWN: return KeyReleased(VK_DOWN); | |
| case ACTION_MENU_LEFT: return KeyReleased(VK_LEFT); | |
| case ACTION_MENU_RIGHT: return KeyReleased(VK_RIGHT); | |
| case ACTION_MENU_OK: | |
| case ACTION_MENU_A: return KeyReleased(VK_RETURN); | |
| case ACTION_MENU_CANCEL: | |
| case ACTION_MENU_B: return KeyReleased(VK_ESCAPE); | |
| case ACTION_MENU_X: return KeyReleased('R'); | |
| case ACTION_MENU_Y: return KeyReleased('T'); | |
| case MINECRAFT_ACTION_FORWARD: return KeyReleased('W'); | |
| case MINECRAFT_ACTION_BACKWARD: return KeyReleased('S'); | |
| case MINECRAFT_ACTION_LEFT: return KeyReleased('A'); | |
| case MINECRAFT_ACTION_RIGHT: return KeyReleased('D'); | |
| case MINECRAFT_ACTION_JUMP: return KeyReleased(VK_SPACE); | |
| case MINECRAFT_ACTION_INVENTORY: return KeyReleased('R'); | |
| case MINECRAFT_ACTION_DROP: return KeyReleased('Z'); | |
| case MINECRAFT_ACTION_ACTION: return KeyReleased(VK_LBUTTON); | |
| case MINECRAFT_ACTION_USE: return KeyReleased(VK_RBUTTON); | |
| //AUXILARY ACTIONS | |
| case MINECRAFT_ACTION_RENDER_THIRD_PERSON: return KeyReleased(VK_F5); | |
| case MINECRAFT_ACTION_PAUSEMENU: return KeyReleased(VK_ESCAPE); | |
| case MINECRAFT_ACTION_CRAFTING: return KeyReleased('T'); | |
| case MINECRAFT_ACTION_SNEAK_TOGGLE: return KeyReleased(VK_LSHIFT); | |
| //DPAD | |
| case MINECRAFT_ACTION_DPAD_UP: return KeyReleased('I'); | |
| case MINECRAFT_ACTION_DPAD_DOWN: return KeyReleased('K'); | |
| case MINECRAFT_ACTION_DPAD_LEFT: return KeyReleased('J'); | |
| case MINECRAFT_ACTION_DPAD_RIGHT: return KeyReleased('L'); | |
| case MINECRAFT_ACTION_LEFT_SCROLL: return KeyReleased('1'); | |
| case MINECRAFT_ACTION_RIGHT_SCROLL: return KeyReleased('2'); | |
| case ACTION_MENU_LEFT_SCROLL: return KeyReleased('Q'); | |
| case ACTION_MENU_RIGHT_SCROLL: return KeyReleased('E'); | |
| case ACTION_MENU_OTHER_STICK_PRESS: | |
| case ACTION_MENU_STICK_PRESS: return KeyReleased(VK_LCONTROL); | |
| } | |
| return false; | |
| } | |
| bool C_4JInput::ButtonDown(int iPad, unsigned char ucAction) | |
| { | |
| if (!IsWindowFocused()) | |
| return false; | |
| switch (ucAction) { | |
| //MAIN CONTROLS | |
| case ACTION_MENU_UP: return KeyDown(VK_UP); | |
| case ACTION_MENU_DOWN: return KeyDown(VK_DOWN); | |
| case ACTION_MENU_LEFT: return KeyDown(VK_LEFT); | |
| case ACTION_MENU_RIGHT: return KeyDown(VK_RIGHT); | |
| case ACTION_MENU_OK: | |
| case ACTION_MENU_A: return KeyDown(VK_RETURN); | |
| case ACTION_MENU_CANCEL: | |
| case ACTION_MENU_B: return KeyDown(VK_ESCAPE); | |
| case ACTION_MENU_X: return KeyDown('R'); | |
| case ACTION_MENU_Y: return KeyDown('T'); | |
| case MINECRAFT_ACTION_FORWARD: return KeyDown('W'); | |
| case MINECRAFT_ACTION_BACKWARD: return KeyDown('S'); | |
| case MINECRAFT_ACTION_LEFT: return KeyDown('A'); | |
| case MINECRAFT_ACTION_RIGHT: return KeyDown('D'); | |
| case MINECRAFT_ACTION_JUMP: return KeyDown(VK_SPACE); | |
| case MINECRAFT_ACTION_INVENTORY: return KeyDown('R'); | |
| case MINECRAFT_ACTION_DROP: return KeyDown('Z'); | |
| case MINECRAFT_ACTION_ACTION: return KeyDown(VK_LBUTTON); | |
| case MINECRAFT_ACTION_USE: return KeyDown(VK_RBUTTON); | |
| //AUXILARY ACTIONS | |
| case MINECRAFT_ACTION_RENDER_THIRD_PERSON: return KeyDown(VK_F5); | |
| case MINECRAFT_ACTION_PAUSEMENU: return KeyDown(VK_ESCAPE); | |
| case MINECRAFT_ACTION_CRAFTING: return KeyDown('T'); | |
| case MINECRAFT_ACTION_SNEAK_TOGGLE: return KeyDown(VK_LSHIFT); | |
| //DPAD | |
| case MINECRAFT_ACTION_DPAD_UP: return KeyDown('I'); | |
| case MINECRAFT_ACTION_DPAD_DOWN: return KeyDown('K'); | |
| case MINECRAFT_ACTION_DPAD_LEFT: return KeyDown('J'); | |
| case MINECRAFT_ACTION_DPAD_RIGHT: return KeyDown('L'); | |
| case MINECRAFT_ACTION_LEFT_SCROLL: return KeyDown('1'); | |
| case MINECRAFT_ACTION_RIGHT_SCROLL: return KeyDown('2'); | |
| case ACTION_MENU_LEFT_SCROLL: return KeyDown('Q'); | |
| case ACTION_MENU_RIGHT_SCROLL: return KeyDown('E'); | |
| case ACTION_MENU_OTHER_STICK_PRESS: | |
| case ACTION_MENU_STICK_PRESS: return KeyDown(VK_LCONTROL); | |
| } | |
| return false; | |
| } | |
| /*bool C_4JInput::ButtonPressedDirect(int key) { | |
| return KeyPressed(key); | |
| } | |
| */ | |
| unsigned int C_4JInput::GetValue(int iPad, unsigned char ucAction, bool bRepeat) | |
| { | |
| return ButtonDown(iPad, ucAction); | |
| } | |
| void C_4JInput::SetJoypadStickAxisMap(int iPad, unsigned int uiFrom, unsigned int uiTo) | |
| { | |
| } | |
| void C_4JInput::SetJoypadStickTriggerMap(int iPad, unsigned int uiFrom, unsigned int uiTo) | |
| { | |
| } | |
| void C_4JInput::SetKeyRepeatRate(float fRepeatDelaySecs, float fRepeatRateSecs) | |
| { | |
| } | |
| void C_4JInput::SetDebugSequence(const char* chSequenceA, int(*Func)(LPVOID), LPVOID lpParam) | |
| { | |
| } | |
| FLOAT C_4JInput::GetIdleSeconds(int iPad) | |
| { | |
| return 0.0f; | |
| } | |
| bool C_4JInput::IsPadConnected(int iPad) | |
| { | |
| if (iPad == 0) return true; | |
| return false; | |
| } | |
| float C_4JInput::GetJoypadStick_LX(int iPad, bool bCheckMenuDisplay) | |
| { | |
| if (!IsWindowFocused()) | |
| return 0.0f; | |
| if (KeyDown('A')) { | |
| return -1.0f; | |
| } else if (KeyDown('D')) { | |
| return 1.0f; | |
| } | |
| return 0.0f; | |
| } | |
| float C_4JInput::GetJoypadStick_LY(int iPad, bool bCheckMenuDisplay) | |
| { | |
| if (!IsWindowFocused()) | |
| return 0.0f; | |
| if (KeyDown('W')) { | |
| return 1.0f; | |
| } else if (KeyDown('S')) { | |
| return -1.0f; | |
| } | |
| return 0.0f; | |
| } | |
| float C_4JInput::GetJoypadStick_RX(int iPad, bool bCheckMenuDisplay) | |
| { | |
| if (!IsWindowFocused()) | |
| return 0.0f; | |
| return MouseEmu::GetRX(); | |
| } | |
| float C_4JInput::GetJoypadStick_RY(int iPad, bool bCheckMenuDisplay) | |
| { | |
| if (!IsWindowFocused()) | |
| return 0.0f; | |
| return MouseEmu::GetRY(); | |
| } | |
| unsigned char C_4JInput::GetJoypadLTrigger(int iPad, bool bCheckMenuDisplay) | |
| { | |
| if (!IsWindowFocused()) | |
| return 0; | |
| if (KeyDown(VK_RBUTTON)) { | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| unsigned char C_4JInput::GetJoypadRTrigger(int iPad, bool bCheckMenuDisplay) | |
| { | |
| if (!IsWindowFocused()) | |
| return 0; | |
| if (KeyDown(VK_LBUTTON)) { | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| void C_4JInput::SetMenuDisplayed(int iPad, bool bVal) | |
| { | |
| } | |
| EKeyboardResult C_4JInput::RequestKeyboard(LPCWSTR Title, LPCWSTR Text, DWORD dwPad, UINT uiMaxChars, int( *Func)(LPVOID,const bool),LPVOID lpParam,C_4JInput::EKeyboardMode eMode) | |
| { | |
| return EKeyboard_Pending; | |
| } | |
| void C_4JInput::GetText(uint16_t* UTF16String) | |
| { | |
| } | |
| bool C_4JInput::VerifyStrings( | |
| WCHAR** pwStringA, | |
| int iStringC, | |
| int(*Func)(LPVOID, STRING_VERIFY_RESPONSE*), | |
| LPVOID lpParam) | |
| { | |
| return false; | |
| } | |
| void C_4JInput::CancelQueuedVerifyStrings( | |
| int(*Func)(LPVOID, STRING_VERIFY_RESPONSE*), | |
| LPVOID lpParam) | |
| { | |
| } | |
| void C_4JInput::CancelAllVerifyInProgress(void) | |
| { | |
| } |
Controls are as follows:
- WASD for movement
- Mouse for camera
- 1 for hotbar left
- 2 for hotbar right
- Q for menu scroll left
- E for menu scroll right
- R for inventory
- T for crafting
- Shift for crouch
- I for debug flight
- K for debug menu
- Esc for menu close / B on controller / Pause
Based on original by @nommiin
Thank you so much!
how do you scroll down on the menu
how do you scroll down on the menu
You use the arrows to navigate the start menu
mb i meant like the creative menu
what do you mean with compile?
could not open source file "Windows64\4JLibs\inc\4J_Input.h" (no directories in search list). says it in vs code
cannot open source file "stdafx.h"
in the main menu the cursor skips down two steps instead of one, making some options impossible to access, also the sensitivity of the hotbar is very high, but otherwise this works really nicely. also maybe seperate the binds for the pause menu and b and such
also thanks for making this
mb i meant like the creative menu
For the controlls shown as Controller button left and Controller button right, you use q and e respectively.
could not open source file "Windows64\4JLibs\inc\4J_Input.h" (no directories in search list). says it in vs code
Wait VS Code? You're supposed to compile this in Visual Studio 2012 in C++ mode with the Windows 8 SDK installed
in the main menu the cursor skips down two steps instead of one, making some options impossible to access, also the sensitivity of the hotbar is very high, but otherwise this works really nicely. also maybe seperate the binds for the pause menu and b and such
I have noticed that, I may fix it, but considering smartcmd has a fork of the source with WAY more advanced mouse support, I'll even wanna bother. Link to that other fork is https://github.com/smartcmd/MinecraftConsoles
also thanks for making this
No problem! I like messing around with random stuff like this.
Where I need to place that file
Where I need to place that file
Everything is explained in the first message below the code, open Minecraft.Client, make a new file named input_keyboard.cpp there, paste the code in, save and compile
What is the button for a?
On Windows 11, go to View -> Show -> File Name Extensions. Then, go into the Minecraft.Client folder, make a new file, name it input_keyboard.cpp, paste the content of the code block above. Compile, and it should run. Mouse doesnt work all the time, if it doesnt work, alt tab out of the game and then into it.