diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index b80eaed..628b330 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -52,6 +52,11 @@ #endif #include "DLCTexturePack.h" +#ifdef _WINDOWS64 +#include "Xbox\Network\NetworkPlayerXbox.h" +#include "Common\Network\PlatformNetworkManagerStub.h" +#endif + #ifdef _DURANGO #include "..\Minecraft.World\DurangoStats.h" #include "..\Minecraft.World\GenericStats.h" @@ -758,6 +763,27 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) player->displayName = player->name; #endif +#ifdef _WINDOWS64 + { + PlayerUID pktXuid = player->getXuid(); + const PlayerUID WIN64_XUID_BASE = (PlayerUID)0xe000d45248242f2e; + if (pktXuid >= WIN64_XUID_BASE && pktXuid < WIN64_XUID_BASE + MINECRAFT_NET_MAX_PLAYERS) + { + BYTE smallId = (BYTE)(pktXuid - WIN64_XUID_BASE); + INetworkPlayer *np = g_NetworkManager.GetPlayerBySmallId(smallId); + if (np != NULL) + { + NetworkPlayerXbox *npx = (NetworkPlayerXbox *)np; + IQNetPlayer *qp = npx->GetQNetPlayer(); + if (qp != NULL && qp->m_gamertag[0] == 0) + { + wcsncpy_s(qp->m_gamertag, 32, packet->name.c_str(), _TRUNCATE); + } + } + } + } +#endif + // printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot); int item = packet->carriedItem; @@ -893,6 +919,39 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr p void ClientConnection::handleRemoveEntity(shared_ptr packet) { +#ifdef _WINDOWS64 + if (!g_NetworkManager.IsHost()) + { + for (int i = 0; i < packet->ids.length; i++) + { + shared_ptr entity = getEntity(packet->ids[i]); + if (entity != NULL && entity->GetType() == eTYPE_PLAYER) + { + shared_ptr player = dynamic_pointer_cast(entity); + if (player != NULL) + { + PlayerUID xuid = player->getXuid(); + INetworkPlayer *np = g_NetworkManager.GetPlayerByXuid(xuid); + if (np != NULL) + { + NetworkPlayerXbox *npx = (NetworkPlayerXbox *)np; + IQNetPlayer *qp = npx->GetQNetPlayer(); + if (qp != NULL) + { + extern CPlatformNetworkManagerStub *g_pPlatformNetworkManager; + g_pPlatformNetworkManager->NotifyPlayerLeaving(qp); + qp->m_smallId = 0; + qp->m_isRemote = false; + qp->m_isHostPlayer = false; + qp->m_gamertag[0] = 0; + qp->SetCustomDataValue(0); + } + } + } + } + } + } +#endif for (int i = 0; i < packet->ids.length; i++) { level->removeEntity(packet->ids[i]); diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp index 24d5243..0a69cd6 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp @@ -240,6 +240,28 @@ void CPlatformNetworkManagerStub::DoWork() IQNet::s_playerCount--; } } + + for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++) + { + IQNetPlayer *qp = &IQNet::m_player[i]; + if (qp->GetCustomDataValue() == 0) + continue; + INetworkPlayer *np = (INetworkPlayer *)qp->GetCustomDataValue(); + Socket *sock = np->GetSocket(); + if (sock != NULL && sock->isClosing()) + { + WinsockNetLayer::CloseConnectionBySmallId((BYTE)i); + } + } + } + if (_iQNetStubState == QNET_STATE_GAME_PLAY && !m_pIQNet->IsHost()) + { + if (!WinsockNetLayer::IsConnected() && !g_NetworkManager.IsLeavingGame()) + { + if (app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) + app.SetDisconnectReason(DisconnectPacket::eDisconnect_Quitting); + app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ExitWorld, (void *)TRUE); + } } #endif } @@ -811,7 +833,21 @@ INetworkPlayer * CPlatformNetworkManagerStub::GetPlayerByXuid(PlayerUID xuid) INetworkPlayer * CPlatformNetworkManagerStub::GetPlayerBySmallId(unsigned char smallId) { - return getNetworkPlayer(m_pIQNet->GetPlayerBySmallId(smallId)); + IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(smallId); + if (qnetPlayer == NULL) + return NULL; + + INetworkPlayer *networkPlayer = getNetworkPlayer(qnetPlayer); +#ifdef _WINDOWS64 + if (networkPlayer == NULL && smallId != 0 && !m_pIQNet->IsHost()) + { + qnetPlayer->m_isRemote = true; + qnetPlayer->m_isHostPlayer = false; + NotifyPlayerJoined(qnetPlayer); + networkPlayer = getNetworkPlayer(qnetPlayer); + } +#endif + return networkPlayer; } INetworkPlayer *CPlatformNetworkManagerStub::GetHostPlayer() diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp index dac2f6e..1b4f37e 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp @@ -471,7 +471,7 @@ void IUIScene_AbstractContainerMenu::onMouseTick() #endif #ifdef _WINDOWS64 - if (!g_KBMInput.IsMouseGrabbed()) + if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { int deltaX = g_KBMInput.GetMouseDeltaX(); int deltaY = g_KBMInput.GetMouseDeltaY(); @@ -716,7 +716,7 @@ void IUIScene_AbstractContainerMenu::onMouseTick() // If there is no stick input, and we are over a slot, then snap pointer to slot centre. // 4J - TomK - only if this particular component allows so! #ifdef _WINDOWS64 - if(g_KBMInput.IsMouseGrabbed() && CanHaveFocus(eSectionUnderPointer)) + if((g_KBMInput.IsMouseGrabbed() || !g_KBMInput.IsKBMActive()) && CanHaveFocus(eSectionUnderPointer)) #else if(CanHaveFocus(eSectionUnderPointer)) #endif diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp index e94e83f..caf3209 100644 --- a/Minecraft.Client/Common/UI/UIController.cpp +++ b/Minecraft.Client/Common/UI/UIController.cpp @@ -691,7 +691,7 @@ void UIController::tickInput() #endif { #ifdef _WINDOWS64 - if (!g_KBMInput.IsMouseGrabbed()) + if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { UIScene *pScene = NULL; for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp) @@ -729,20 +729,23 @@ void UIController::tickInput() S32 numFocusables = 0; IggyPlayerGetFocusableObjects(movie, ¤tFocus, focusables, 64, &numFocusables); - IggyFocusHandle hitObject = IGGY_FOCUS_NULL; - for (S32 i = 0; i < numFocusables; ++i) + if (numFocusables > 0 && numFocusables <= 64) { - if (mouseX >= focusables[i].x0 && mouseX <= focusables[i].x1 && - mouseY >= focusables[i].y0 && mouseY <= focusables[i].y1) + IggyFocusHandle hitObject = IGGY_FOCUS_NULL; + for (S32 i = 0; i < numFocusables; ++i) { - hitObject = focusables[i].object; - break; + if (mouseX >= focusables[i].x0 && mouseX <= focusables[i].x1 && + mouseY >= focusables[i].y0 && mouseY <= focusables[i].y1) + { + hitObject = focusables[i].object; + break; + } } - } - if (hitObject != IGGY_FOCUS_NULL && hitObject != currentFocus) - { - IggyPlayerSetFocusRS(movie, hitObject, 0); + if (hitObject != IGGY_FOCUS_NULL && hitObject != currentFocus) + { + IggyPlayerSetFocusRS(movie, hitObject, 0); + } } if (g_KBMInput.IsMouseButtonDown(0) || g_KBMInput.IsMouseButtonPressed(0)) diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp index 704d736..a1b144b 100644 --- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp @@ -45,6 +45,7 @@ void UIScene_AbstractContainerMenu::handleDestroy() g_savedInventoryCursorPos.y = m_pointerPos.y; g_savedInventoryCursorPos.hasSavedPos = true; + g_KBMInput.SetScreenCursorHidden(false); g_KBMInput.SetCursorHiddenForUI(false); #endif @@ -82,6 +83,7 @@ void UIScene_AbstractContainerMenu::InitDataAssociations(int iPad, AbstractConta void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex) { #ifdef _WINDOWS64 + g_KBMInput.SetScreenCursorHidden(true); g_KBMInput.SetCursorHiddenForUI(true); #endif diff --git a/Minecraft.Client/Extrax64Stubs.cpp b/Minecraft.Client/Extrax64Stubs.cpp index 4ebd89e..9db5776 100644 --- a/Minecraft.Client/Extrax64Stubs.cpp +++ b/Minecraft.Client/Extrax64Stubs.cpp @@ -168,7 +168,7 @@ void PIXSetMarkerDeprecated(int a, char *b, ...) {} bool IsEqualXUID(PlayerUID a, PlayerUID b) { -#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) || defined(_DURANGO) +#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) || defined(_DURANGO) || defined(_WINDOWS64) return (a == b); #else return false; @@ -232,13 +232,17 @@ void Win64_SetupRemoteQNetPlayer(IQNetPlayer *player, BYTE smallId, bool isHost, IQNet::s_playerCount = smallId + 1; } +static bool Win64_IsActivePlayer(IQNetPlayer *p, DWORD index); + HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex){ return S_OK; } IQNetPlayer *IQNet::GetHostPlayer() { return &m_player[0]; } IQNetPlayer *IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex) { if (s_isHosting) { - if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && !m_player[dwUserIndex].m_isRemote) + if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && + !m_player[dwUserIndex].m_isRemote && + Win64_IsActivePlayer(&m_player[dwUserIndex], dwUserIndex)) return &m_player[dwUserIndex]; return NULL; } @@ -246,7 +250,7 @@ IQNetPlayer *IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex) return NULL; for (DWORD i = 0; i < s_playerCount; i++) { - if (!m_player[i].m_isRemote) + if (!m_player[i].m_isRemote && Win64_IsActivePlayer(&m_player[i], i)) return &m_player[i]; } return NULL; @@ -272,19 +276,21 @@ IQNetPlayer *IQNet::GetPlayerByIndex(DWORD dwPlayerIndex) } IQNetPlayer *IQNet::GetPlayerBySmallId(BYTE SmallId) { - for (DWORD i = 0; i < s_playerCount; i++) - { - if (m_player[i].m_smallId == SmallId && Win64_IsActivePlayer(&m_player[i], i)) return &m_player[i]; - } - return NULL; + if (SmallId >= MINECRAFT_NET_MAX_PLAYERS) + return NULL; + + m_player[SmallId].m_smallId = SmallId; + if (SmallId >= s_playerCount) + s_playerCount = SmallId + 1; + return &m_player[SmallId]; } IQNetPlayer *IQNet::GetPlayerByXuid(PlayerUID xuid) { - for (DWORD i = 0; i < s_playerCount; i++) + for (DWORD i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) { if (Win64_IsActivePlayer(&m_player[i], i) && m_player[i].GetXuid() == xuid) return &m_player[i]; } - return &m_player[0]; + return NULL; } DWORD IQNet::GetPlayerCount() { @@ -299,15 +305,28 @@ QNET_STATE IQNet::GetState() { return _iQNetStubState; } bool IQNet::IsHost() { return s_isHosting; } HRESULT IQNet::JoinGameFromInviteInfo(DWORD dwUserIndex, DWORD dwUserMask, const INVITE_INFO *pInviteInfo) { return S_OK; } void IQNet::HostGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = true; } -void IQNet::ClientJoinGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = false; } +void IQNet::ClientJoinGame() +{ + _iQNetStubState = QNET_STATE_SESSION_STARTING; + s_isHosting = false; + + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) + { + m_player[i].m_smallId = (BYTE)i; + m_player[i].m_isRemote = true; + m_player[i].m_isHostPlayer = false; + m_player[i].m_gamertag[0] = 0; + m_player[i].SetCustomDataValue(0); + } +} void IQNet::EndGame() { _iQNetStubState = QNET_STATE_IDLE; s_isHosting = false; s_playerCount = 1; - for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++) + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) { - m_player[i].m_smallId = 0; + m_player[i].m_smallId = (BYTE)i; m_player[i].m_isRemote = false; m_player[i].m_isHostPlayer = false; m_player[i].m_gamertag[0] = 0; diff --git a/Minecraft.Client/Input.cpp b/Minecraft.Client/Input.cpp index 6772b3c..b44e81b 100644 --- a/Minecraft.Client/Input.cpp +++ b/Minecraft.Client/Input.cpp @@ -46,7 +46,7 @@ void Input::tick(LocalPlayer *player) float kbXA = 0.0f; float kbYA = 0.0f; #ifdef _WINDOWS64 - if (iPad == 0 && g_KBMInput.IsMouseGrabbed()) + if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT) ) kbXA = g_KBMInput.GetMoveX(); @@ -94,7 +94,7 @@ void Input::tick(LocalPlayer *player) } #ifdef _WINDOWS64 - if (iPad == 0 && g_KBMInput.IsMouseGrabbed()) + if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { // Left Shift = sneak (hold to crouch) if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE)) @@ -166,7 +166,7 @@ void Input::tick(LocalPlayer *player) float turnY = ty * abs(ty) * turnSpeed; #ifdef _WINDOWS64 - if (iPad == 0 && g_KBMInput.IsMouseGrabbed()) + if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { float mouseSensitivity = ((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame)) / 100.0f; float mouseLookScale = 5.0f; @@ -190,7 +190,7 @@ void Input::tick(LocalPlayer *player) unsigned int jump = InputManager.GetValue(iPad, MINECRAFT_ACTION_JUMP); bool kbJump = false; #ifdef _WINDOWS64 - kbJump = (iPad == 0) && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_JUMP); + kbJump = (iPad == 0) && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_JUMP); #endif if( (jump > 0 || kbJump) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP) ) jumping = true; diff --git a/Minecraft.Client/KeyboardMouseInput.cpp b/Minecraft.Client/KeyboardMouseInput.cpp index 4d5855c..8308e9b 100644 --- a/Minecraft.Client/KeyboardMouseInput.cpp +++ b/Minecraft.Client/KeyboardMouseInput.cpp @@ -36,6 +36,8 @@ void KeyboardMouseInput::Init() m_cursorHiddenForUI = false; m_windowFocused = true; m_hasInput = false; + m_kbmActive = true; + m_screenWantsCursorHidden = false; RAWINPUTDEVICE rid; rid.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC diff --git a/Minecraft.Client/KeyboardMouseInput.h b/Minecraft.Client/KeyboardMouseInput.h index 88ecd8b..b19452d 100644 --- a/Minecraft.Client/KeyboardMouseInput.h +++ b/Minecraft.Client/KeyboardMouseInput.h @@ -80,6 +80,12 @@ public: bool HasAnyInput() const { return m_hasInput; } + void SetKBMActive(bool active) { m_kbmActive = active; } + bool IsKBMActive() const { return m_kbmActive; } + + void SetScreenCursorHidden(bool hidden) { m_screenWantsCursorHidden = hidden; } + bool IsScreenCursorHidden() const { return m_screenWantsCursorHidden; } + float GetMoveX() const; float GetMoveY() const; @@ -121,6 +127,10 @@ private: bool m_windowFocused; bool m_hasInput; + + bool m_kbmActive; + + bool m_screenWantsCursorHidden; }; extern KeyboardMouseInput g_KBMInput; diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index f83b336..de408b3 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -1457,7 +1457,7 @@ void Minecraft::run_middle() { if(InputManager.ButtonDown(i, MINECRAFT_ACTION_SNEAK_TOGGLE)) localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL< 0) + localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<inventory) + localplayers[i]->inventory->selected = slot; + } + } + } + + // Utility keys always work regardless of KBM active state if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE)) { localplayers[i]->ullButtonsPressed|=1LL< 0) - localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<inventory) - localplayers[i]->inventory->selected = slot; - } - } } #endif @@ -3267,7 +3271,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) wheel = -1; } #ifdef _WINDOWS64 - if (iPad == 0 && wheel == 0) + if (iPad == 0 && wheel == 0 && g_KBMInput.IsKBMActive()) { int mw = g_KBMInput.GetMouseWheel(); if (mw > 0) wheel = -1; @@ -3297,7 +3301,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) } #ifdef _WINDOWS64 // allows for the player to get the block they are looking at in creative by middle clicking. - if (iPad == 0 && player->abilities.instabuild && g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_MIDDLE) && hitResult != NULL && (hitResult->type == HitResult::TILE || hitResult->type == HitResult::ENTITY)) + if (iPad == 0 && g_KBMInput.IsKBMActive() && player->abilities.instabuild && g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_MIDDLE) && hitResult != NULL && (hitResult->type == HitResult::TILE || hitResult->type == HitResult::ENTITY)) { //printf("MIDDLE CLICK TEST!!"); // windermed was here. int cloneId = -1; @@ -3390,7 +3394,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) } #ifdef _WINDOWS64 - bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) || (iPad == 0 && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT)); + bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) || (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT)); #else bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION); #endif @@ -3421,7 +3425,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) } */ #ifdef _WINDOWS64 - bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT)); + bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT)); #else bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE); #endif diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp index 19fc259..7e7c6ae 100644 --- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp +++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp @@ -213,6 +213,14 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) s_isHost = false; s_hostSmallId = 0; + s_connected = false; + s_active = false; + + if (s_hostConnectionSocket != INVALID_SOCKET) + { + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + } struct addrinfo hints = {}; struct addrinfo *result = NULL; @@ -231,37 +239,55 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) return false; } - s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); - if (s_hostConnectionSocket == INVALID_SOCKET) + bool connected = false; + BYTE assignedSmallId = 0; + const int maxAttempts = 12; + + for (int attempt = 0; attempt < maxAttempts; ++attempt) { - app.DebugPrintf("socket() failed: %d\n", WSAGetLastError()); - freeaddrinfo(result); - return false; + s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + if (s_hostConnectionSocket == INVALID_SOCKET) + { + app.DebugPrintf("socket() failed: %d\n", WSAGetLastError()); + break; + } + + int noDelay = 1; + setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); + + iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen); + if (iResult == SOCKET_ERROR) + { + int err = WSAGetLastError(); + app.DebugPrintf("connect() to %s:%d failed (attempt %d/%d): %d\n", ip, port, attempt + 1, maxAttempts, err); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + Sleep(200); + continue; + } + + BYTE assignBuf[1]; + int bytesRecv = recv(s_hostConnectionSocket, (char *)assignBuf, 1, 0); + if (bytesRecv != 1) + { + app.DebugPrintf("Failed to receive small ID assignment from host (attempt %d/%d)\n", attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + Sleep(200); + continue; + } + + assignedSmallId = assignBuf[0]; + connected = true; + break; } - - int noDelay = 1; - setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); - - iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen); freeaddrinfo(result); - if (iResult == SOCKET_ERROR) - { - app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, WSAGetLastError()); - closesocket(s_hostConnectionSocket); - s_hostConnectionSocket = INVALID_SOCKET; - return false; - } - BYTE assignBuf[1]; - int bytesRecv = recv(s_hostConnectionSocket, (char *)assignBuf, 1, 0); - if (bytesRecv != 1) + if (!connected) { - app.DebugPrintf("Failed to receive small ID assignment from host\n"); - closesocket(s_hostConnectionSocket); - s_hostConnectionSocket = INVALID_SOCKET; return false; } - s_localSmallId = assignBuf[0]; + s_localSmallId = assignedSmallId; app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId); @@ -479,7 +505,8 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param) BYTE clientSmallId = s_connections[connIdx].smallId; LeaveCriticalSection(&s_connectionsLock); - BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE]; + std::vector recvBuf; + recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE); while (s_active) { @@ -490,33 +517,47 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param) break; } - int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3]; + int packetSize = + ((uint32_t)header[0] << 24) | + ((uint32_t)header[1] << 16) | + ((uint32_t)header[2] << 8) | + ((uint32_t)header[3]); - if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE) + if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE) { - app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d\n", packetSize, clientSmallId); + app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d (max=%d)\n", + packetSize, + clientSmallId, + (int)WIN64_NET_MAX_PACKET_SIZE); break; } - if (!RecvExact(sock, recvBuf, packetSize)) + if ((int)recvBuf.size() < packetSize) + { + recvBuf.resize(packetSize); + app.DebugPrintf("Win64 LAN: Resized host recv buffer to %d bytes for client smallId=%d\n", packetSize, clientSmallId); + } + + if (!RecvExact(sock, &recvBuf[0], packetSize)) { app.DebugPrintf("Win64 LAN: Client smallId=%d disconnected (body)\n", clientSmallId); break; } - HandleDataReceived(clientSmallId, s_hostSmallId, recvBuf, packetSize); + HandleDataReceived(clientSmallId, s_hostSmallId, &recvBuf[0], packetSize); } - delete[] recvBuf; - EnterCriticalSection(&s_connectionsLock); for (size_t i = 0; i < s_connections.size(); i++) { if (s_connections[i].smallId == clientSmallId) { s_connections[i].active = false; - closesocket(s_connections[i].tcpSocket); - s_connections[i].tcpSocket = INVALID_SOCKET; + if (s_connections[i].tcpSocket != INVALID_SOCKET) + { + closesocket(s_connections[i].tcpSocket); + s_connections[i].tcpSocket = INVALID_SOCKET; + } break; } } @@ -550,9 +591,26 @@ void WinsockNetLayer::PushFreeSmallId(BYTE smallId) LeaveCriticalSection(&s_freeSmallIdLock); } +void WinsockNetLayer::CloseConnectionBySmallId(BYTE smallId) +{ + EnterCriticalSection(&s_connectionsLock); + for (size_t i = 0; i < s_connections.size(); i++) + { + if (s_connections[i].smallId == smallId && s_connections[i].active && s_connections[i].tcpSocket != INVALID_SOCKET) + { + closesocket(s_connections[i].tcpSocket); + s_connections[i].tcpSocket = INVALID_SOCKET; + app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId); + break; + } + } + LeaveCriticalSection(&s_connectionsLock); +} + DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param) { - BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE]; + std::vector recvBuf; + recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE); while (s_active && s_hostConnectionSocket != INVALID_SOCKET) { @@ -565,23 +623,29 @@ DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param) int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3]; - if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE) + if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE) { - app.DebugPrintf("Win64 LAN: Invalid packet size %d from host\n", packetSize); + app.DebugPrintf("Win64 LAN: Invalid packet size %d from host (max=%d)\n", + packetSize, + (int)WIN64_NET_MAX_PACKET_SIZE); break; } - if (!RecvExact(s_hostConnectionSocket, recvBuf, packetSize)) + if ((int)recvBuf.size() < packetSize) + { + recvBuf.resize(packetSize); + app.DebugPrintf("Win64 LAN: Resized client recv buffer to %d bytes\n", packetSize); + } + + if (!RecvExact(s_hostConnectionSocket, &recvBuf[0], packetSize)) { app.DebugPrintf("Win64 LAN: Disconnected from host (body)\n"); break; } - HandleDataReceived(s_hostSmallId, s_localSmallId, recvBuf, packetSize); + HandleDataReceived(s_hostSmallId, s_localSmallId, &recvBuf[0], packetSize); } - delete[] recvBuf; - s_connected = false; return 0; } diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.h b/Minecraft.Client/Windows64/Network/WinsockNetLayer.h index 96b03c9..e6ace42 100644 --- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.h +++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.h @@ -12,6 +12,7 @@ #define WIN64_NET_DEFAULT_PORT 25565 #define WIN64_NET_MAX_CLIENTS 7 #define WIN64_NET_RECV_BUFFER_SIZE 65536 +#define WIN64_NET_MAX_PACKET_SIZE (4 * 1024 * 1024) #define WIN64_LAN_DISCOVERY_PORT 25566 #define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E @@ -81,6 +82,7 @@ public: static bool PopDisconnectedSmallId(BYTE *outSmallId); static void PushFreeSmallId(BYTE smallId); + static void CloseConnectionBySmallId(BYTE smallId); static bool StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer); static void StopAdvertising(); diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index f3bc185..bef05fe 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -1185,6 +1185,33 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, PIXBeginNamedEvent(0,"Input manager tick"); InputManager.Tick(); + // detect input mode + if (InputManager.IsPadConnected(0)) + { + bool controllerUsed = InputManager.ButtonPressed(0) || + InputManager.GetJoypadStick_LX(0, false) != 0.0f || + InputManager.GetJoypadStick_LY(0, false) != 0.0f || + InputManager.GetJoypadStick_RX(0, false) != 0.0f || + InputManager.GetJoypadStick_RY(0, false) != 0.0f; + + if (controllerUsed) + g_KBMInput.SetKBMActive(false); + else if (g_KBMInput.HasAnyInput()) + g_KBMInput.SetKBMActive(true); + } + else + { + g_KBMInput.SetKBMActive(true); + } + + if (!g_KBMInput.IsMouseGrabbed()) + { + if (!g_KBMInput.IsKBMActive()) + g_KBMInput.SetCursorHiddenForUI(true); + else if (!g_KBMInput.IsScreenCursorHidden()) + g_KBMInput.SetCursorHiddenForUI(false); + } + PIXEndNamedEvent(); PIXBeginNamedEvent(0,"Profile manager tick"); // ProfileManager.Tick();