diff options
| author | Sean Hoyt <seanhoyt963@gmail.com> | 2026-03-01 10:50:48 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-02 00:50:48 +0800 |
| commit | b5111232aa13952f58ed1b3b3525ea825662b95c (patch) | |
| tree | 2e7450af7d442c6337e33bba0d81f5cb38622806 /Minecraft.Client/Minecraft.cpp | |
| parent | d5707899dbc99d5c9520095246fc0bf2425c6235 (diff) | |
feat: Windows64 local multiplayer support (#13)
- Skip QuadrantSignin (profile selector) on Windows64 in both LoadMenu
and CreateWorldMenu, proceeding directly to local play since Xbox Live
stubs always return true for IsSignedInLive()
- Fix IsLocalMultiplayerAvailable() to not require IsHiDef() on Windows64
- Allow pad-connected players to join without a profile sign-in check
- Fix ghost RemotePlayer creation by scanning all local player slots and
matching on server-assigned player index rather than controller slot,
fixing P3/P4 ghost entities when joining out of controller order
- Give each player a unique name (Player 1-4) based on controller index
instead of a single shared stub name
- Use raw XInput (XInputGetState) for secondary controller join detection,
bypassing the 4J toggle system which consumes all button presses before
game logic runs; uses a 120-frame latch for a reliable detection window
- Add .gitignore for Visual Studio build artifacts and output directories
Diffstat (limited to 'Minecraft.Client/Minecraft.cpp')
| -rw-r--r-- | Minecraft.Client/Minecraft.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index ff8346be..3192410d 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -1564,7 +1564,31 @@ void Minecraft::run_middle() // 4J Stu - This doesn't make any sense with the way we handle XboxOne users #ifndef _DURANGO // did we just get input from a player who doesn't exist? They'll be wanting to join the game then +#ifdef _WINDOWS64 + // The 4J toggle system is unreliable here: UIController::handleInput() calls + // ButtonPressed for every ACTION_MENU_* mapped button (which covers all physical + // buttons) before run_middle() runs. Bypass it with raw XInput and own edge detection. + // A latch counter keeps startJustPressed active for ~120 frames after the rising edge + // so the detection window is large enough to be caught reliably. + static WORD s_prevXButtons[XUSER_MAX_COUNT] = {}; + static int s_startPressLatch[XUSER_MAX_COUNT] = {}; + XINPUT_STATE xstate_join; + memset(&xstate_join, 0, sizeof(xstate_join)); + WORD xCurButtons = 0; + if (XInputGetState(i, &xstate_join) == ERROR_SUCCESS) + { + xCurButtons = xstate_join.Gamepad.wButtons; + if ((xCurButtons & XINPUT_GAMEPAD_START) != 0 && (s_prevXButtons[i] & XINPUT_GAMEPAD_START) == 0) + s_startPressLatch[i] = 120; // rising edge: latch for ~120 frames (~2s at 60fps) + else if (s_startPressLatch[i] > 0) + s_startPressLatch[i]--; + s_prevXButtons[i] = xCurButtons; + } + bool startJustPressed = s_startPressLatch[i] > 0; + bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && xCurButtons != 0; +#else bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && RenderManager.IsHiDef() && InputManager.ButtonPressed(i); +#endif #ifdef __ORBIS__ // Check for remote play tryJoin = tryJoin && InputManager.IsLocalMultiplayerAvailable(); @@ -1592,6 +1616,8 @@ void Minecraft::run_middle() // did we just get input from a player who doesn't exist? They'll be wanting to join the game then #ifdef __ORBIS__ if(InputManager.ButtonPressed(i, ACTION_MENU_A)) +#elif defined _WINDOWS64 + if(startJustPressed) #else if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_PAUSEMENU)) #endif @@ -1599,7 +1625,11 @@ void Minecraft::run_middle() // Let them join // are they signed in? +#ifdef _WINDOWS64 + if(ProfileManager.IsSignedIn(i) || (g_NetworkManager.IsLocalGame() && InputManager.IsPadConnected(i))) +#else if(ProfileManager.IsSignedIn(i)) +#endif { // if this is a local game, then the player just needs to be signed in if( g_NetworkManager.IsLocalGame() || (ProfileManager.IsSignedInLive(i) && ProfileManager.AllowedToPlayMultiplayer(i) ) ) |
