aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 18:50:55 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 19:20:41 +0800
commitbdef1f9412d21757bc4a21ed905daff32fd0df27 (patch)
tree26f8aad48a60a67b8e3c61ac94005456427716a4
parent9af787692e3925d70c9f29eca3c47bdb7479d076 (diff)
feat: add support for keyboard and mouse input
-rw-r--r--Minecraft.Client/Common/UI/UIController.cpp23
-rw-r--r--Minecraft.Client/Input.cpp57
-rw-r--r--Minecraft.Client/Input.h3
-rw-r--r--Minecraft.Client/LocalPlayer.cpp9
-rw-r--r--Minecraft.Client/Minecraft.Client.vcxproj90
-rw-r--r--Minecraft.Client/Minecraft.Client.vcxproj.filters6
-rw-r--r--Minecraft.Client/Minecraft.cpp76
-rw-r--r--Minecraft.Client/Windows64/KeyboardMouseInput.cpp217
-rw-r--r--Minecraft.Client/Windows64/KeyboardMouseInput.h76
-rw-r--r--Minecraft.Client/Windows64/Windows64_Minecraft.cpp84
-rw-r--r--Minecraft.Client/stdafx.h3
-rw-r--r--README.md23
12 files changed, 640 insertions, 27 deletions
diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp
index 7493ff06..8045695e 100644
--- a/Minecraft.Client/Common/UI/UIController.cpp
+++ b/Minecraft.Client/Common/UI/UIController.cpp
@@ -919,6 +919,29 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
pressed = InputManager.ButtonPressed(iPad,key); // Toggle
released = InputManager.ButtonReleased(iPad,key); // Toggle
+#ifdef _WINDOWS64
+ // Keyboard menu input for player 0
+ if (iPad == 0)
+ {
+ bool kbDown = false, kbPressed = false, kbReleased = false;
+ switch(key)
+ {
+ case ACTION_MENU_UP: kbDown = KMInput.IsKeyDown(VK_UP); kbPressed = KMInput.IsKeyPressed(VK_UP); kbReleased = KMInput.IsKeyReleased(VK_UP); break;
+ case ACTION_MENU_DOWN: kbDown = KMInput.IsKeyDown(VK_DOWN); kbPressed = KMInput.IsKeyPressed(VK_DOWN); kbReleased = KMInput.IsKeyReleased(VK_DOWN); break;
+ case ACTION_MENU_LEFT: kbDown = KMInput.IsKeyDown(VK_LEFT); kbPressed = KMInput.IsKeyPressed(VK_LEFT); kbReleased = KMInput.IsKeyReleased(VK_LEFT); break;
+ case ACTION_MENU_RIGHT: kbDown = KMInput.IsKeyDown(VK_RIGHT); kbPressed = KMInput.IsKeyPressed(VK_RIGHT); kbReleased = KMInput.IsKeyReleased(VK_RIGHT); break;
+ case ACTION_MENU_OK: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break;
+ case ACTION_MENU_A: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break;
+ case ACTION_MENU_CANCEL: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break;
+ case ACTION_MENU_B: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break;
+ case ACTION_MENU_PAUSEMENU: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break;
+ }
+ pressed = pressed || kbPressed;
+ released = released || kbReleased;
+ down = down || kbDown;
+ }
+#endif
+
if(pressed) app.DebugPrintf("Pressed %d\n",key);
if(released) app.DebugPrintf("Released %d\n",key);
// Repeat handling
diff --git a/Minecraft.Client/Input.cpp b/Minecraft.Client/Input.cpp
index 645f3477..d9f83d09 100644
--- a/Minecraft.Client/Input.cpp
+++ b/Minecraft.Client/Input.cpp
@@ -18,6 +18,7 @@ Input::Input()
lReset = false;
rReset = false;
+ m_gamepadSneaking = false;
}
void Input::tick(LocalPlayer *player)
@@ -34,12 +35,30 @@ void Input::tick(LocalPlayer *player)
xa = -InputManager.GetJoypadStick_LX(iPad);
else
xa = 0.0f;
-
+
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD) )
ya = InputManager.GetJoypadStick_LY(iPad);
else
ya = 0.0f;
+#ifdef _WINDOWS64
+ // WASD movement (combine with gamepad)
+ if (iPad == 0)
+ {
+ float kbX = 0.0f, kbY = 0.0f;
+ if (KMInput.IsKeyDown('W')) kbY += 1.0f;
+ if (KMInput.IsKeyDown('S')) kbY -= 1.0f;
+ if (KMInput.IsKeyDown('A')) kbX += 1.0f; // inverted like gamepad
+ if (KMInput.IsKeyDown('D')) kbX -= 1.0f;
+ // Normalize diagonal
+ if (kbX != 0.0f && kbY != 0.0f) { kbX *= 0.707f; kbY *= 0.707f; }
+ if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT))
+ xa = max(min(xa + kbX, 1.0f), -1.0f);
+ if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD))
+ ya = max(min(ya + kbY, 1.0f), -1.0f);
+ }
+#endif
+
#ifndef _CONTENT_PACKAGE
if (app.GetFreezePlayers())
{
@@ -47,7 +66,7 @@ void Input::tick(LocalPlayer *player)
player->abilities.flying = true;
}
#endif
-
+
if (!lReset)
{
if (xa*xa+ya*ya==0.0f)
@@ -62,9 +81,16 @@ void Input::tick(LocalPlayer *player)
{
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE)) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE))
{
- sneaking=!sneaking;
+ m_gamepadSneaking=!m_gamepadSneaking;
}
}
+ sneaking = m_gamepadSneaking;
+
+#ifdef _WINDOWS64
+ // Keyboard hold-to-sneak (overrides gamepad toggle)
+ if (iPad == 0 && KMInput.IsKeyDown(VK_SHIFT) && !player->abilities.flying)
+ sneaking = true;
+#endif
if(sneaking)
{
@@ -80,7 +106,7 @@ void Input::tick(LocalPlayer *player)
tx = InputManager.GetJoypadStick_RX(iPad)*(((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame))/100.0f); // apply sensitivity to look
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_UP) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_DOWN) )
ty = InputManager.GetJoypadStick_RY(iPad)*(((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame))/100.0f); // apply sensitivity to look
-
+
#ifndef _CONTENT_PACKAGE
if (app.GetFreezePlayers()) tx = ty = 0.0f;
#endif
@@ -100,16 +126,35 @@ void Input::tick(LocalPlayer *player)
tx = ty = 0.0f;
}
player->interpolateTurn(tx * abs(tx) * turnSpeed, ty * abs(ty) * turnSpeed);
-
+
+#ifdef _WINDOWS64
+ // Mouse look (added after stick-based turn)
+ if (iPad == 0 && KMInput.IsCaptured())
+ {
+ float mouseSensitivity = 1.25f;
+ float mdx = KMInput.GetMouseDeltaX() * mouseSensitivity;
+ float mdy = -KMInput.GetMouseDeltaY() * mouseSensitivity;
+ if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
+ mdy = -mdy;
+ player->interpolateTurn(mdx, mdy);
+ }
+#endif
+
//jumping = controller.isButtonPressed(0);
-
+
unsigned int jump = InputManager.GetValue(iPad, MINECRAFT_ACTION_JUMP);
if( jump > 0 && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP) )
jumping = true;
else
jumping = false;
+#ifdef _WINDOWS64
+ // Keyboard jump (Space)
+ if (iPad == 0 && KMInput.IsKeyDown(VK_SPACE) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP))
+ jumping = true;
+#endif
+
#ifndef _CONTENT_PACKAGE
if (app.GetFreezePlayers()) jumping = false;
#endif
diff --git a/Minecraft.Client/Input.h b/Minecraft.Client/Input.h
index 0a44d765..ef1dcd0c 100644
--- a/Minecraft.Client/Input.h
+++ b/Minecraft.Client/Input.h
@@ -16,7 +16,8 @@ public:
virtual void tick(LocalPlayer *player);
private:
-
+
bool lReset;
bool rReset;
+ bool m_gamepadSneaking;
}; \ No newline at end of file
diff --git a/Minecraft.Client/LocalPlayer.cpp b/Minecraft.Client/LocalPlayer.cpp
index ea66b9e1..aabd6a2b 100644
--- a/Minecraft.Client/LocalPlayer.cpp
+++ b/Minecraft.Client/LocalPlayer.cpp
@@ -302,6 +302,15 @@ void LocalPlayer::aiStep()
// world with low food, then reload it in creative.
if(abilities.mayfly || isAllowedToFly() ) enoughFoodToSprint = true;
+#ifdef _WINDOWS64
+ // Keyboard sprint: Ctrl held while moving forward
+ if (GetXboxPad() == 0 && KMInput.IsKeyDown(VK_CONTROL) && input->ya > 0.0f &&
+ enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness) && onGround)
+ {
+ if (!isSprinting()) setSprinting(true);
+ }
+#endif
+
// 4J - altered this slightly to make sure that the joypad returns to below returnTreshold in between registering two movements up to runThreshold
if (onGround && !isSprinting() && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness))
{
diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj
index 6473c537..38886043 100644
--- a/Minecraft.Client/Minecraft.Client.vcxproj
+++ b/Minecraft.Client/Minecraft.Client.vcxproj
@@ -16292,6 +16292,51 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
</ClInclude>
+ <ClInclude Include="Windows64\KeyboardMouseInput.h">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugContentPackage|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
+ </ClInclude>
<ClInclude Include="Windows64\Sentient\DynamicConfigurations.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
@@ -29101,6 +29146,51 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
</ClCompile>
+ <ClCompile Include="Windows64\KeyboardMouseInput.cpp">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugContentPackage|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Durango'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PS3'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
+ </ClCompile>
<ClCompile Include="Windows64\Windows64_UIController.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
diff --git a/Minecraft.Client/Minecraft.Client.vcxproj.filters b/Minecraft.Client/Minecraft.Client.vcxproj.filters
index ca698851..7731385c 100644
--- a/Minecraft.Client/Minecraft.Client.vcxproj.filters
+++ b/Minecraft.Client/Minecraft.Client.vcxproj.filters
@@ -2341,6 +2341,9 @@
<ClInclude Include="Windows64\Resource.h">
<Filter>Windows64</Filter>
</ClInclude>
+ <ClInclude Include="Windows64\KeyboardMouseInput.h">
+ <Filter>Windows64\Source Files</Filter>
+ </ClInclude>
<ClInclude Include="Windows64\Windows64_App.h">
<Filter>Windows64</Filter>
</ClInclude>
@@ -4770,6 +4773,9 @@
<ClCompile Include="Windows64\Windows64_Minecraft.cpp">
<Filter>Windows64\Source Files</Filter>
</ClCompile>
+ <ClCompile Include="Windows64\KeyboardMouseInput.cpp">
+ <Filter>Windows64\Source Files</Filter>
+ </ClCompile>
<ClCompile Include="Windows64\Windows64_App.cpp">
<Filter>Windows64</Filter>
</ClCompile>
diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp
index 1892fb36..7290d521 100644
--- a/Minecraft.Client/Minecraft.cpp
+++ b/Minecraft.Client/Minecraft.cpp
@@ -1452,6 +1452,21 @@ void Minecraft::run_middle()
if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_RENDER_THIRD_PERSON)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_GAME_INFO)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_GAME_INFO;
+#ifdef _WINDOWS64
+ // Keyboard/mouse button presses for player 0
+ if (i == 0)
+ {
+ if (KMInput.IsKeyPressed(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_PAUSEMENU;
+ if (KMInput.IsKeyPressed('E')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY;
+ if (KMInput.IsKeyPressed('Q')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP;
+ if (KMInput.IsKeyPressed('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING;
+ if (KMInput.IsKeyPressed(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
+ // In flying mode, Shift held = sneak/descend
+ if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT))
+ localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
+ }
+#endif
+
#ifndef _FINAL_BUILD
if( app.DebugSettingsOn() && app.GetUseDPadForDebug() )
{
@@ -3177,6 +3192,30 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
{
wheel = -1;
}
+
+#ifdef _WINDOWS64
+ // Mouse scroll wheel for hotbar
+ if (iPad == 0)
+ {
+ int kbWheel = KMInput.GetScrollDelta();
+ if (kbWheel > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) wheel += 1;
+ else if (kbWheel < 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL)) wheel -= 1;
+
+ // 1-9 keys for direct hotbar selection
+ if (gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL))
+ {
+ for (int k = '1'; k <= '9'; k++)
+ {
+ if (KMInput.IsKeyPressed(k))
+ {
+ player->inventory->selected = k - '1';
+ app.SetOpacityTimer(iPad);
+ break;
+ }
+ }
+ }
+ }
+#endif
if (wheel != 0)
{
player->inventory->swapPaint(wheel);
@@ -3208,6 +3247,13 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
player->handleMouseClick(0);
player->lastClickTick[0] = ticks;
}
+#ifdef _WINDOWS64
+ else if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMousePressed(0))
+ {
+ player->handleMouseClick(0);
+ player->lastClickTick[0] = ticks;
+ }
+#endif
if (InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4)
{
@@ -3215,8 +3261,19 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
player->handleMouseClick(0);
player->lastClickTick[0] = ticks;
}
+#ifdef _WINDOWS64
+ else if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4)
+ {
+ player->handleMouseClick(0);
+ player->lastClickTick[0] = ticks;
+ }
+#endif
- if(InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) )
+ if(InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION)
+#ifdef _WINDOWS64
+ || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0))
+#endif
+ )
{
player->handleMouseDown(0, true );
}
@@ -3237,14 +3294,23 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
*/
if( player->isUsingItem() )
{
- if(!InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE)) gameMode->releaseUsingItem(player);
+ if(!InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE)
+#ifdef _WINDOWS64
+ && !(iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1))
+#endif
+ ) gameMode->releaseUsingItem(player);
}
else if( gameMode->isInputAllowed(MINECRAFT_ACTION_USE) )
{
+#ifdef _WINDOWS64
+ bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1));
+#else
+ bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE);
+#endif
if( player->abilities.instabuild )
{
// 4J - attempt to handle click in special creative mode fashion if possible (used for placing blocks at regular intervals)
- bool didClick = player->creativeModeHandleMouseClick(1, InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) );
+ bool didClick = player->creativeModeHandleMouseClick(1, useButtonDown );
// If this handler has put us in lastClick_oldRepeat mode then it is because we aren't placing blocks - behave largely as the code used to
if( player->lastClickState == LocalPlayer::lastClick_oldRepeat )
{
@@ -3256,7 +3322,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
else
{
// Otherwise just the original game code for handling autorepeat
- if (InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4)
+ if (useButtonDown && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4)
{
player->handleMouseClick(1);
player->lastClickTick[1] = ticks;
@@ -3272,7 +3338,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
bool firstClick = ( player->lastClickTick[1] == 0 );
bool autoRepeat = ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4;
if ( player->isRiding() || player->isSprinting() || player->isSleeping() ) autoRepeat = false;
- if (InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) )
+ if (useButtonDown )
{
// If the player has just exited a bed, then delay the time before a repeat key is allowed without releasing
if(player->isSleeping() ) player->lastClickTick[1] = ticks + (timer->ticksPerSecond * 2);
diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp
new file mode 100644
index 00000000..e67946da
--- /dev/null
+++ b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp
@@ -0,0 +1,217 @@
+#include "stdafx.h"
+
+#ifdef _WINDOWS64
+
+#include "KeyboardMouseInput.h"
+
+KeyboardMouseInput KMInput;
+
+KeyboardMouseInput::KeyboardMouseInput()
+ : m_mouseDeltaX(0.0f)
+ , m_mouseDeltaY(0.0f)
+ , m_mouseDeltaXAccum(0.0f)
+ , m_mouseDeltaYAccum(0.0f)
+ , m_scrollDelta(0)
+ , m_scrollDeltaAccum(0)
+ , m_captured(false)
+ , m_hWnd(NULL)
+ , m_initialized(false)
+{
+ memset(m_keyState, 0, sizeof(m_keyState));
+ memset(m_keyStatePrev, 0, sizeof(m_keyStatePrev));
+ memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
+ memset(m_mouseButtonsPrev, 0, sizeof(m_mouseButtonsPrev));
+}
+
+KeyboardMouseInput::~KeyboardMouseInput()
+{
+ if (m_captured)
+ {
+ SetCapture(false);
+ }
+}
+
+void KeyboardMouseInput::Init(HWND hWnd)
+{
+ m_hWnd = hWnd;
+ m_initialized = true;
+
+ // Register for raw mouse input
+ RAWINPUTDEVICE rid;
+ rid.usUsagePage = HID_USAGE_PAGE_GENERIC;
+ rid.usUsage = HID_USAGE_GENERIC_MOUSE;
+ rid.dwFlags = 0;
+ rid.hwndTarget = hWnd;
+ RegisterRawInputDevices(&rid, 1, sizeof(rid));
+}
+
+void KeyboardMouseInput::Tick()
+{
+ // Snapshot accumulated mouse deltas
+ m_mouseDeltaX = m_mouseDeltaXAccum;
+ m_mouseDeltaY = m_mouseDeltaYAccum;
+ m_mouseDeltaXAccum = 0.0f;
+ m_mouseDeltaYAccum = 0.0f;
+
+ // Snapshot scroll delta
+ m_scrollDelta = m_scrollDeltaAccum;
+ m_scrollDeltaAccum = 0;
+
+ // Keep cursor pinned to center while captured
+ if (m_captured)
+ CenterCursor();
+}
+
+void KeyboardMouseInput::EndFrame()
+{
+ // Advance previous state for next frame's edge detection.
+ // Must be called AFTER all consumers have read IsKeyPressed/Released etc.
+ memcpy(m_keyStatePrev, m_keyState, sizeof(m_keyState));
+ memcpy(m_mouseButtonsPrev, m_mouseButtons, sizeof(m_mouseButtons));
+}
+
+void KeyboardMouseInput::OnKeyDown(WPARAM vk)
+{
+ if (vk < 256)
+ {
+ m_keyState[vk] = true;
+ }
+}
+
+void KeyboardMouseInput::OnKeyUp(WPARAM vk)
+{
+ if (vk < 256)
+ {
+ m_keyState[vk] = false;
+ }
+}
+
+void KeyboardMouseInput::OnRawMouseInput(LPARAM lParam)
+{
+ if (!m_captured) return;
+
+ UINT dwSize = 0;
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
+
+ BYTE* lpb = (BYTE*)alloca(dwSize);
+ if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
+ return;
+
+ RAWINPUT* raw = (RAWINPUT*)lpb;
+ if (raw->header.dwType == RIM_TYPEMOUSE)
+ {
+ if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE)
+ {
+ m_mouseDeltaXAccum += (float)raw->data.mouse.lLastX;
+ m_mouseDeltaYAccum += (float)raw->data.mouse.lLastY;
+ }
+ }
+}
+
+void KeyboardMouseInput::OnMouseButton(int button, bool down)
+{
+ if (button >= 0 && button < 3)
+ {
+ m_mouseButtons[button] = down;
+ }
+}
+
+void KeyboardMouseInput::OnMouseWheel(int delta)
+{
+ m_scrollDeltaAccum += delta;
+}
+
+void KeyboardMouseInput::ClearAllState()
+{
+ memset(m_keyState, 0, sizeof(m_keyState));
+ memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
+ m_mouseDeltaXAccum = 0.0f;
+ m_mouseDeltaYAccum = 0.0f;
+ m_scrollDeltaAccum = 0;
+}
+
+// Key queries
+bool KeyboardMouseInput::IsKeyDown(int vk) const
+{
+ if (vk < 0 || vk >= 256) return false;
+ return m_keyState[vk];
+}
+
+bool KeyboardMouseInput::IsKeyPressed(int vk) const
+{
+ if (vk < 0 || vk >= 256) return false;
+ return m_keyState[vk] && !m_keyStatePrev[vk];
+}
+
+bool KeyboardMouseInput::IsKeyReleased(int vk) const
+{
+ if (vk < 0 || vk >= 256) return false;
+ return !m_keyState[vk] && m_keyStatePrev[vk];
+}
+
+// Mouse button queries
+bool KeyboardMouseInput::IsMouseDown(int btn) const
+{
+ if (btn < 0 || btn >= 3) return false;
+ return m_mouseButtons[btn];
+}
+
+bool KeyboardMouseInput::IsMousePressed(int btn) const
+{
+ if (btn < 0 || btn >= 3) return false;
+ return m_mouseButtons[btn] && !m_mouseButtonsPrev[btn];
+}
+
+bool KeyboardMouseInput::IsMouseReleased(int btn) const
+{
+ if (btn < 0 || btn >= 3) return false;
+ return !m_mouseButtons[btn] && m_mouseButtonsPrev[btn];
+}
+
+// Delta queries
+float KeyboardMouseInput::GetMouseDeltaX() const { return m_mouseDeltaX; }
+float KeyboardMouseInput::GetMouseDeltaY() const { return m_mouseDeltaY; }
+int KeyboardMouseInput::GetScrollDelta() const { return m_scrollDelta; }
+
+// Mouse capture
+void KeyboardMouseInput::SetCapture(bool capture)
+{
+ if (capture == m_captured) return;
+ m_captured = capture;
+
+ if (capture)
+ {
+ ShowCursor(FALSE);
+ RECT rect;
+ GetClientRect(m_hWnd, &rect);
+ POINT topLeft = { rect.left, rect.top };
+ POINT bottomRight = { rect.right, rect.bottom };
+ ClientToScreen(m_hWnd, &topLeft);
+ ClientToScreen(m_hWnd, &bottomRight);
+ RECT screenRect = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y };
+ ClipCursor(&screenRect);
+ CenterCursor();
+
+ // Flush accumulated deltas so the snap-to-center doesn't cause a jump
+ m_mouseDeltaXAccum = 0.0f;
+ m_mouseDeltaYAccum = 0.0f;
+ }
+ else
+ {
+ ShowCursor(TRUE);
+ ClipCursor(NULL);
+ }
+}
+
+bool KeyboardMouseInput::IsCaptured() const { return m_captured; }
+
+void KeyboardMouseInput::CenterCursor()
+{
+ RECT rect;
+ GetClientRect(m_hWnd, &rect);
+ POINT center = { (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 };
+ ClientToScreen(m_hWnd, &center);
+ SetCursorPos(center.x, center.y);
+}
+
+#endif // _WINDOWS64
diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.h b/Minecraft.Client/Windows64/KeyboardMouseInput.h
new file mode 100644
index 00000000..722c9f3d
--- /dev/null
+++ b/Minecraft.Client/Windows64/KeyboardMouseInput.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#ifdef _WINDOWS64
+
+#include <windows.h>
+
+// HID usage page and usage for raw input registration
+#ifndef HID_USAGE_PAGE_GENERIC
+#define HID_USAGE_PAGE_GENERIC ((USHORT)0x01)
+#endif
+#ifndef HID_USAGE_GENERIC_MOUSE
+#define HID_USAGE_GENERIC_MOUSE ((USHORT)0x02)
+#endif
+
+class KeyboardMouseInput
+{
+public:
+ KeyboardMouseInput();
+ ~KeyboardMouseInput();
+
+ void Init(HWND hWnd);
+ void Tick();
+ void EndFrame();
+
+ // Called from WndProc
+ void OnKeyDown(WPARAM vk);
+ void OnKeyUp(WPARAM vk);
+ void OnRawMouseInput(LPARAM lParam);
+ void OnMouseButton(int button, bool down);
+ void OnMouseWheel(int delta);
+ void ClearAllState();
+
+ // Key state queries (call after Tick)
+ bool IsKeyDown(int vk) const;
+ bool IsKeyPressed(int vk) const;
+ bool IsKeyReleased(int vk) const;
+
+ // Mouse button queries: 0=left, 1=right, 2=middle
+ bool IsMouseDown(int btn) const;
+ bool IsMousePressed(int btn) const;
+ bool IsMouseReleased(int btn) const;
+
+ // Mouse deltas (consumed each Tick)
+ float GetMouseDeltaX() const;
+ float GetMouseDeltaY() const;
+ int GetScrollDelta() const;
+
+ // Mouse capture for FPS look
+ void SetCapture(bool capture);
+ bool IsCaptured() const;
+
+private:
+ void CenterCursor();
+
+ bool m_keyState[256];
+ bool m_keyStatePrev[256];
+
+ bool m_mouseButtons[3];
+ bool m_mouseButtonsPrev[3];
+
+ float m_mouseDeltaX;
+ float m_mouseDeltaY;
+ float m_mouseDeltaXAccum;
+ float m_mouseDeltaYAccum;
+
+ int m_scrollDelta;
+ int m_scrollDeltaAccum;
+
+ bool m_captured;
+ HWND m_hWnd;
+ bool m_initialized;
+};
+
+extern KeyboardMouseInput KMInput;
+
+#endif // _WINDOWS64
diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
index d2251e4e..4002fc3b 100644
--- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
+++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
@@ -339,6 +339,63 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_DESTROY:
PostQuitMessage(0);
break;
+
+ // Keyboard/Mouse input handling
+ case WM_KEYDOWN:
+ if (!(lParam & 0x40000000)) // ignore auto-repeat
+ KMInput.OnKeyDown(wParam);
+ break;
+ case WM_KEYUP:
+ KMInput.OnKeyUp(wParam);
+ break;
+ case WM_SYSKEYDOWN:
+ if (wParam == VK_MENU) // Alt key
+ {
+ if (!(lParam & 0x40000000))
+ KMInput.OnKeyDown(wParam);
+ return 0; // prevent default Alt behavior
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU)
+ {
+ KMInput.OnKeyUp(wParam);
+ return 0;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ case WM_INPUT:
+ KMInput.OnRawMouseInput(lParam);
+ break;
+ case WM_LBUTTONDOWN:
+ KMInput.OnMouseButton(0, true);
+ break;
+ case WM_LBUTTONUP:
+ KMInput.OnMouseButton(0, false);
+ break;
+ case WM_RBUTTONDOWN:
+ KMInput.OnMouseButton(1, true);
+ break;
+ case WM_RBUTTONUP:
+ KMInput.OnMouseButton(1, false);
+ break;
+ case WM_MBUTTONDOWN:
+ KMInput.OnMouseButton(2, true);
+ break;
+ case WM_MBUTTONUP:
+ KMInput.OnMouseButton(2, false);
+ break;
+ case WM_MOUSEWHEEL:
+ KMInput.OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam));
+ break;
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE)
+ KMInput.SetCapture(false);
+ break;
+ case WM_KILLFOCUS:
+ KMInput.SetCapture(false);
+ KMInput.ClearAllState();
+ break;
+
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
@@ -715,6 +772,9 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// Set the number of possible joypad layouts that the user can switch between, and the number of actions
InputManager.Initialise(1,3,MINECRAFT_ACTION_MAX, ACTION_MAX_MENU);
+ // Initialize keyboard/mouse input
+ KMInput.Init(g_hWnd);
+
// Set the default joypad action mappings for Minecraft
DefineActions();
InputManager.SetJoypadMapVal(0,0);
@@ -940,6 +1000,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
app.UpdateTime();
PIXBeginNamedEvent(0,"Input manager tick");
InputManager.Tick();
+ KMInput.Tick();
PIXEndNamedEvent();
PIXBeginNamedEvent(0,"Profile manager tick");
// ProfileManager.Tick();
@@ -1067,6 +1128,27 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
RenderManager.Present();
ui.CheckMenuDisplayed();
+
+ // Update mouse capture: capture when in-game and no menu is open
+ {
+ static bool altToggleSuppressCapture = false;
+ bool shouldCapture = app.GetGameStarted() && !ui.GetMenuDisplayed(0);
+ // Left Alt key toggles capture on/off for debugging
+ if (KMInput.IsKeyPressed(VK_MENU))
+ {
+ if (KMInput.IsCaptured()) { KMInput.SetCapture(false); altToggleSuppressCapture = true; }
+ else if (shouldCapture) { KMInput.SetCapture(true); altToggleSuppressCapture = false; }
+ }
+ else if (!shouldCapture)
+ {
+ if (KMInput.IsCaptured()) KMInput.SetCapture(false);
+ altToggleSuppressCapture = false;
+ }
+ else if (shouldCapture && !KMInput.IsCaptured() && GetFocus() == g_hWnd && !altToggleSuppressCapture)
+ {
+ KMInput.SetCapture(true);
+ }
+ }
#if 0
PIXBeginNamedEvent(0,"Profile load check");
// has the game defined profile data been changed (by a profile load)
@@ -1158,6 +1240,8 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// Fix for #7318 - Title crashes after short soak in the leaderboards menu
// A memory leak was caused because the icon renderer kept creating new Vec3's because the pool wasn't reset
Vec3::resetPool();
+
+ KMInput.EndFrame();
}
// Free resources, unregister custom classes, and exit.
diff --git a/Minecraft.Client/stdafx.h b/Minecraft.Client/stdafx.h
index a7ba7b06..60cd4667 100644
--- a/Minecraft.Client/stdafx.h
+++ b/Minecraft.Client/stdafx.h
@@ -174,10 +174,11 @@ typedef XUID GameSessionUID;
#include "Durango\4JLibs\inc\4J_Render.h"
#include "Durango\4JLibs\inc\4J_Storage.h"
#elif defined _WINDOWS64
- #include "Windows64\4JLibs\inc\4J_Input.h"
+ #include "Windows64\4JLibs\inc\4J_Input.h"
#include "Windows64\4JLibs\inc\4J_Profile.h"
#include "Windows64\4JLibs\inc\4J_Render.h"
#include "Windows64\4JLibs\inc\4J_Storage.h"
+ #include "Windows64\KeyboardMouseInput.h"
#elif defined __PSVITA__
#include "PSVita\4JLibs\inc\4J_Input.h"
#include "PSVita\4JLibs\inc\4J_Profile.h"
diff --git a/README.md b/README.md
index 19018bfc..c9e77d11 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,12 @@
## Introduction
-This project contains the source code of Minecraft Legacy Console Edition v1.3.0494.0, with some fixes applied to allow compilation and execution in Debug and Release mode on Windows using Visual Studio 2022.
+This project contains the source code of Minecraft Legacy Console Edition v1.3.0494.0, with some fixes and improvements applied.
+
+## Features
+
+- Fixed compilation and execution in both Debug and Release mode on Windows using Visual Studio 2022
+- Added support for keyboard and mouse input
## Build & Run
@@ -14,18 +19,8 @@ This project contains the source code of Minecraft Legacy Console Edition v1.3.0
4. Make sure `Minecraft.Client` is set as the Startup Project
5. Set the build configuration to **Debug** or **Release** and the target platform to **Windows64**, then build and run
-## Playing
-
-Since Minecraft Legacy Console Edition does not natively support keyboard and mouse input, you will need to use a gamepad to play, or use a virtual gamepad emulator such as [QKeyMapper](https://github.com/Zalafina/QKeyMapper).
-
## Known Issues
-1. Builds for other platforms have not been tested and are most likely non-functional.
-2. Sound effects are missing.
-3. Other unknown issues may exist.
-
-## Goals
-
-- [ ] Native keyboard and mouse input support
-- [x] Fix compilation in Release mode on Windows
-- [ ] Fix builds and execution on non-Windows platforms
+- Builds for other platforms have not been tested and are most likely non-functional
+- Sound effects are missing
+- Other unknown issues may exist \ No newline at end of file