diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index d4fa38c5..4fdac440 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -50,11 +50,16 @@ #else #include "Common\UI\UI.h" #endif -#ifdef __PS3__ +#if defined __PS3__ && !defined DISABLE_PSN #include "PS3/Network/SonyVoiceChat.h" #endif #include "DLCTexturePack.h" +#if defined _WINDOWS64 || defined DISABLE_PSN || defined _DISABLE_XBLIVE +#include "Xbox\Network\NetworkPlayerXbox.h" +#include "Common\Network\PlatformNetworkManagerStub.h" +#endif + #ifdef _DURANGO #include "..\Minecraft.World\DurangoStats.h" #include "..\Minecraft.World\GenericStats.h" @@ -781,6 +786,32 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) player->m_displayName = player->name; #endif +#if defined _WINDOWS64 || defined DISABLE_PSN || defined _DISABLE_XBLIVE + { + 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) + { + wcsncpy(qp->m_gamertag, packet->name.c_str(), 31); + qp->m_gamertag[31] = L'\0'; + if (g_NetworkManager.IsHost()) + { + g_NetworkManager.UpdateAndSetGameSessionData(); + } + } + } + } + } +#endif + // printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot); int item = packet->carriedItem; @@ -923,6 +954,39 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr p void ClientConnection::handleRemoveEntity(shared_ptr packet) { +#if defined _WINDOWS64 || defined DISABLE_PSN || defined _DISABLE_XBLIVE + 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/GameNetworkManager.cpp b/Minecraft.Client/Common/Network/GameNetworkManager.cpp index 5b94e250..86257604 100644 --- a/Minecraft.Client/Common/Network/GameNetworkManager.cpp +++ b/Minecraft.Client/Common/Network/GameNetworkManager.cpp @@ -1502,7 +1502,10 @@ void CGameNetworkManager::CreateSocket( INetworkPlayer *pNetworkPlayer, bool loc Minecraft *pMinecraft = Minecraft::GetInstance(); Socket *socket = NULL; - shared_ptr mpPlayer = pMinecraft->localplayers[pNetworkPlayer->GetUserIndex()]; + shared_ptr mpPlayer = nullptr; + int userIdx = pNetworkPlayer->GetUserIndex(); + if (userIdx >= 0 && userIdx < XUSER_MAX_COUNT) + mpPlayer = pMinecraft->localplayers[userIdx]; if( localPlayer && mpPlayer != NULL && mpPlayer->connection != NULL) { // If we already have a MultiplayerLocalPlayer here then we are doing a session type change diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp index 9ced020a..0a234252 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp @@ -94,7 +94,7 @@ void CPlatformNetworkManagerStub::NotifyPlayerJoined(IQNetPlayer *pQNetPlayer ) if( m_pIQNet->IsHost() ) { // 4J-PB - only the host should do this -// g_NetworkManager.UpdateAndSetGameSessionData(); + g_NetworkManager.UpdateAndSetGameSessionData(); SystemFlagAddPlayer( networkPlayer ); } @@ -141,6 +141,11 @@ void CPlatformNetworkManagerStub::NotifyPlayerLeaving(IQNetPlayer *pQNetPlayer) g_NetworkManager.PlayerLeaving(networkPlayer); + if (m_pIQNet->IsHost()) + { + g_NetworkManager.UpdateAndSetGameSessionData(networkPlayer); + } + for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx) { if (playerChangedCallback[idx] != NULL) @@ -239,6 +244,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); + } } } @@ -470,44 +497,48 @@ bool CPlatformNetworkManagerStub::_RunNetworkGame() void CPlatformNetworkManagerStub::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving /*= NULL*/) { -// DWORD playerCount = m_pIQNet->GetPlayerCount(); -// -// if( this->m_bLeavingGame ) -// return; -// -// if( GetHostPlayer() == NULL ) -// return; -// -// for(unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) -// { -// if( i < playerCount ) -// { -// INetworkPlayer *pNetworkPlayer = GetPlayerByIndex(i); -// -// // We can call this from NotifyPlayerLeaving but at that point the player is still considered in the session -// if( pNetworkPlayer != pNetworkPlayerLeaving ) -// { -// m_hostGameSessionData.players[i] = ((NetworkPlayerXbox *)pNetworkPlayer)->GetUID(); -// -// char *temp; -// temp = (char *)wstringtofilename( pNetworkPlayer->GetOnlineName() ); -// memcpy(m_hostGameSessionData.szPlayers[i],temp,XUSER_NAME_SIZE); -// } -// else -// { -// m_hostGameSessionData.players[i] = NULL; -// memset(m_hostGameSessionData.szPlayers[i],0,XUSER_NAME_SIZE); -// } -// } -// else -// { -// m_hostGameSessionData.players[i] = NULL; -// memset(m_hostGameSessionData.szPlayers[i],0,XUSER_NAME_SIZE); -// } -// } -// -// m_hostGameSessionData.hostPlayerUID = ((NetworkPlayerXbox *)GetHostPlayer())->GetQNetPlayer()->GetXuid(); -// m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All); + if (this->m_bLeavingGame) + return; + + if (!m_pIQNet->IsHost()) + return; + + DWORD playerCount = m_pIQNet->GetPlayerCount(); + + m_hostGameSessionData.m_uiGameHostSettings = app.GetGameHostOption(eGameHostOption_All); + m_hostGameSessionData.playerCount = (unsigned char)playerCount; + + for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if (i < playerCount) + { + INetworkPlayer *pNetworkPlayer = GetPlayerByIndex(i); + + if (pNetworkPlayer != NULL && pNetworkPlayer != pNetworkPlayerLeaving) + { + m_hostGameSessionData.players[i] = (GameSessionUID)(i + 1); + + const wchar_t *name = pNetworkPlayer->GetOnlineName(); + char nameBuf[XUSER_NAME_SIZE]; + memset(nameBuf, 0, sizeof(nameBuf)); + wcstombs(nameBuf, name, XUSER_NAME_SIZE - 1); + memcpy(m_hostGameSessionData.szPlayers[i], nameBuf, XUSER_NAME_SIZE); + } + else + { + m_hostGameSessionData.players[i] = 0; + memset(m_hostGameSessionData.szPlayers[i], 0, XUSER_NAME_SIZE); + } + } + else + { + m_hostGameSessionData.players[i] = 0; + memset(m_hostGameSessionData.szPlayers[i], 0, XUSER_NAME_SIZE); + } + } + + // update the LAN advertiser with current player names and count + WinsockNetLayer::UpdateAdvertisePlayerNames(m_hostGameSessionData.playerCount, m_hostGameSessionData.szPlayers); } int CPlatformNetworkManagerStub::RemovePlayerOnSocketClosedThreadProc( void* lpParam ) @@ -728,6 +759,17 @@ void CPlatformNetworkManagerStub::SearchForGames() info->data.playerCount = lanSessions[i].playerCount; info->data.maxPlayers = lanSessions[i].maxPlayers; + memset(info->data.players, 0, sizeof(info->data.players)); + memset(info->data.szPlayers, 0, sizeof(info->data.szPlayers)); + for (int p = 0; p < MINECRAFT_NET_MAX_PLAYERS && p < lanSessions[i].playerCount; p++) + { + if (lanSessions[i].playerNames[p][0] != 0) + { + info->data.players[p] = (GameSessionUID)(p + 1); + memcpy(info->data.szPlayers[p], lanSessions[i].playerNames[p], XUSER_NAME_SIZE); + } + } + info->sessionId = (ULONGLONG)((unsigned __int64)inet_addr(lanSessions[i].hostIP) | ((unsigned __int64)lanSessions[i].hostPort << 32)); friendsSessions[0].push_back(info); @@ -760,7 +802,19 @@ vector *CPlatformNetworkManagerStub::GetSessionList(int iPa bool CPlatformNetworkManagerStub::GetGameSessionInfo(int iPad, SessionID sessionId, FriendSessionInfo *foundSessionInfo) { - return false; + for (size_t i = 0; i < friendsSessions[0].size(); i++) + { + if (friendsSessions[0][i]->sessionId == sessionId) + { + if (foundSessionInfo != NULL) + { + foundSessionInfo->sessionId = friendsSessions[0][i]->sessionId; + foundSessionInfo->data = friendsSessions[0][i]->data; + foundSessionInfo->hasPartyMember = friendsSessions[0][i]->hasPartyMember; + } + return true; + } + } } void CPlatformNetworkManagerStub::SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam ) @@ -830,7 +884,19 @@ 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); + if (networkPlayer == NULL && smallId != 0 && !m_pIQNet->IsHost()) + { + qnetPlayer->m_isRemote = true; + qnetPlayer->m_isHostPlayer = false; + NotifyPlayerJoined(qnetPlayer); + networkPlayer = getNetworkPlayer(qnetPlayer); + } + return networkPlayer; } INetworkPlayer *CPlatformNetworkManagerStub::GetHostPlayer() diff --git a/Minecraft.Client/Common/Network/SessionInfo.h b/Minecraft.Client/Common/Network/SessionInfo.h index 982234dc..4d494b9d 100644 --- a/Minecraft.Client/Common/Network/SessionInfo.h +++ b/Minecraft.Client/Common/Network/SessionInfo.h @@ -86,6 +86,9 @@ typedef struct _GameSessionData unsigned char playerCount; // 1 byte unsigned char maxPlayers; // 1 byte + GameSessionUID players[MINECRAFT_NET_MAX_PLAYERS]; + char szPlayers[MINECRAFT_NET_MAX_PLAYERS][XUSER_NAME_SIZE]; + _GameSessionData() { netVersion = 0; @@ -99,6 +102,8 @@ typedef struct _GameSessionData memset(hostName, 0, sizeof(hostName)); playerCount = 0; maxPlayers = MINECRAFT_NET_MAX_PLAYERS; + memset(players, 0, sizeof(players)); + memset(szPlayers, 0, sizeof(szPlayers)); } } GameSessionData; #endif diff --git a/Minecraft.Client/Common/Network/WinsockNetLayer.cpp b/Minecraft.Client/Common/Network/WinsockNetLayer.cpp index 9b75a8df..9a653a47 100644 --- a/Minecraft.Client/Common/Network/WinsockNetLayer.cpp +++ b/Minecraft.Client/Common/Network/WinsockNetLayer.cpp @@ -321,8 +321,18 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) s_isHost = false; s_hostSmallId = 0; + s_connected = false; + s_active = false; + const int maxAttempts = 3; + const int connectTimeoutMs = 3000; #if defined _WINDOWS64 + if (s_hostConnectionSocket != INVALID_SOCKET) + { + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + } + struct addrinfo hints = {}; struct addrinfo *result = NULL; @@ -340,27 +350,97 @@ 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; + + 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)); + + u_long nonBlocking = 1; + ioctlsocket(s_hostConnectionSocket, FIONBIO, &nonBlocking); + + iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen); + if (iResult == SOCKET_ERROR) + { + int err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK) + { + fd_set writeFds, exceptFds; + FD_ZERO(&writeFds); + FD_ZERO(&exceptFds); + FD_SET(s_hostConnectionSocket, &writeFds); + FD_SET(s_hostConnectionSocket, &exceptFds); + + struct timeval tv; + tv.tv_sec = connectTimeoutMs / 1000; + tv.tv_usec = (connectTimeoutMs % 1000) * 1000; + + int selectResult = select(0, NULL, &writeFds, &exceptFds, &tv); + if (selectResult <= 0 || FD_ISSET(s_hostConnectionSocket, &exceptFds)) + { + app.DebugPrintf("connect() to %s:%d timed out or failed (attempt %d/%d)\n", ip, port, attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + continue; + } + + int sockErr = 0; + int sockErrLen = sizeof(sockErr); + getsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_ERROR, (char *)&sockErr, &sockErrLen); + if (sockErr != 0) + { + app.DebugPrintf("connect() to %s:%d failed with SO_ERROR %d (attempt %d/%d)\n", ip, port, sockErr, attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + continue; + } + } + else + { + 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; + continue; + } + } + + u_long blocking = 0; + ioctlsocket(s_hostConnectionSocket, FIONBIO, &blocking); + + DWORD recvTimeout = 3000; + setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&recvTimeout, sizeof(recvTimeout)); + + 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; + 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) +#elif defined _XBOX + if (s_hostConnectionSocket != INVALID_SOCKET) { - app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, WSAGetLastError()); closesocket(s_hostConnectionSocket); s_hostConnectionSocket = INVALID_SOCKET; - return false; } -#elif defined _XBOX + XNDNS *pDns = NULL; int iResult = XNetDnsLookup(ip, NULL, &pDns); if (iResult != 0 || pDns == NULL) @@ -387,25 +467,85 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) addr.sin_addr = pDns->aina[0]; XNetDnsRelease(pDns); - s_hostConnectionSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (s_hostConnectionSocket == INVALID_SOCKET) - { - app.DebugPrintf("socket() failed: %d\n", WSAGetLastError()); - return false; - } + bool connected = false; + BYTE assignedSmallId = 0; - int noDelay = 1; - setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); - - iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); - if (iResult == SOCKET_ERROR) + for (int attempt = 0; attempt < maxAttempts; ++attempt) { - app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, WSAGetLastError()); - closesocket(s_hostConnectionSocket); - s_hostConnectionSocket = INVALID_SOCKET; - return false; + s_hostConnectionSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + 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)); + + u_long nonBlocking = 1; + ioctlsocket(s_hostConnectionSocket, FIONBIO, &nonBlocking); + + iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); + if (iResult == SOCKET_ERROR) + { + int err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK) + { + fd_set writeFds, exceptFds; + FD_ZERO(&writeFds); + FD_ZERO(&exceptFds); + FD_SET(s_hostConnectionSocket, &writeFds); + FD_SET(s_hostConnectionSocket, &exceptFds); + + struct timeval tv; + tv.tv_sec = connectTimeoutMs / 1000; + tv.tv_usec = (connectTimeoutMs % 1000) * 1000; + + int selectResult = select(0, NULL, &writeFds, &exceptFds, &tv); + if (selectResult <= 0 || FD_ISSET(s_hostConnectionSocket, &exceptFds)) + { + app.DebugPrintf("connect() to %s:%d timed out or failed (attempt %d/%d)\n", ip, port, attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + continue; + } + } + else + { + 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; + continue; + } + } + + u_long blocking = 0; + ioctlsocket(s_hostConnectionSocket, FIONBIO, &blocking); + + DWORD recvTimeout = 3000; + setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&recvTimeout, sizeof(recvTimeout)); + + 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; + continue; + } + + assignedSmallId = assignBuf[0]; + connected = true; + break; } #elif defined __PS3__ + if (s_hostConnectionSocket != -1) + { + socketclose(s_hostConnectionSocket); + s_hostConnectionSocket = -1; + } + struct sockaddr_in addr = {}; addr.sin_family = AF_INET; @@ -418,38 +558,108 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) return false; } - int iResult = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - s_hostConnectionSocket = iResult; - if (s_hostConnectionSocket < 0) - { - app.DebugPrintf("socket() failed: %d\n", s_hostConnectionSocket); - return false; - } + bool connected = false; + BYTE assignedSmallId = 0; - int noDelay = 1; - setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); - - iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); - if (iResult < 0) + for (int attempt = 0; attempt < maxAttempts; ++attempt) { - app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, s_hostConnectionSocket); - socketclose(s_hostConnectionSocket); - s_hostConnectionSocket = -1; - return false; + int iResult = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + s_hostConnectionSocket = iResult; + if (s_hostConnectionSocket < 0) + { + app.DebugPrintf("socket() failed: %d\n", s_hostConnectionSocket); + break; + } + + int noDelay = 1; + setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); + + int nonBlocking = 1; + setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_NBIO, &nonBlocking, sizeof(nonBlocking)); + + iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); + if (iResult < 0) + { + int err = sys_net_errno; + if (err == SYS_NET_EINPROGRESS) + { + fd_set writeFds, exceptFds; + FD_ZERO(&writeFds); + FD_ZERO(&exceptFds); + FD_SET(s_hostConnectionSocket, &writeFds); + FD_SET(s_hostConnectionSocket, &exceptFds); + + struct timeval tv; + tv.tv_sec = connectTimeoutMs / 1000; + tv.tv_usec = (connectTimeoutMs % 1000) * 1000; + + int selectResult = socketselect(s_hostConnectionSocket + 1, NULL, &writeFds, &exceptFds, &tv); + if (selectResult <= 0 || FD_ISSET(s_hostConnectionSocket, &exceptFds)) + { + app.DebugPrintf("connect() to %s:%d timed out or failed (attempt %d/%d)\n", ip, port, attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + continue; + } + + int sockErr = 0; + socklen_t sockErrLen = sizeof(sockErr); + getsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_ERROR, (char *)&sockErr, &sockErrLen); + if (sockErr != 0) + { + app.DebugPrintf("connect() to %s:%d failed with SO_ERROR %d (attempt %d/%d)\n", ip, port, sockErr, attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + continue; + } + } + else + { + 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; + continue; + } + } + + int blocking = 0; + setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_NBIO, &blocking, sizeof(blocking)); + + DWORD recvTimeout = 3000; + setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&recvTimeout, sizeof(recvTimeout)); + /* + iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); + if (iResult < 0) + { + app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, s_hostConnectionSocket); + socketclose(s_hostConnectionSocket); + s_hostConnectionSocket = -1; + return false; + } + */ + + 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; + continue; + } + + assignedSmallId = assignBuf[0]; + connected = true; + break; } #endif - 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); + app.DebugPrintf("LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId); s_active = true; s_connected = true; @@ -698,7 +908,8 @@ int 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) { @@ -709,33 +920,47 @@ int 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("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) { - app.DebugPrintf("Win64 LAN: Client smallId=%d disconnected (body)\n", clientSmallId); + recvBuf.resize(packetSize); + app.DebugPrintf("LAN: Resized host recv buffer to %d bytes for client smallId=%d\n", packetSize, clientSmallId); + } + + if (!RecvExact(sock, &recvBuf[0], packetSize)) + { + app.DebugPrintf("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; } } @@ -769,9 +994,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); +} + int WinsockNetLayer::ClientRecvThreadProc(LPVOID param) { - BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE]; + std::vector recvBuf; + recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE); #if defined _WINDOWS64 || defined _XBOX while (s_active && s_hostConnectionSocket != INVALID_SOCKET) @@ -782,29 +1024,33 @@ int WinsockNetLayer::ClientRecvThreadProc(LPVOID param) BYTE header[4]; if (!RecvExact(s_hostConnectionSocket, header, 4)) { - app.DebugPrintf("Win64 LAN: Disconnected from host (header)\n"); + app.DebugPrintf("LAN: Disconnected from host (header)\n"); break; } 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("LAN: Invalid packet size %d from host\n", packetSize); break; } - if (!RecvExact(s_hostConnectionSocket, recvBuf, packetSize)) + if ((int)recvBuf.size() < packetSize) { - app.DebugPrintf("Win64 LAN: Disconnected from host (body)\n"); + recvBuf.resize(packetSize); + app.DebugPrintf("LAN: Resized client recv buffer to %d bytes\n", packetSize); + } + + if (!RecvExact(s_hostConnectionSocket, &recvBuf[0], packetSize)) + { + app.DebugPrintf("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; } @@ -887,6 +1133,18 @@ void WinsockNetLayer::UpdateAdvertisePlayerCount(BYTE count) LeaveCriticalSection(&s_advertiseLock); } +void WinsockNetLayer::UpdateAdvertisePlayerNames(BYTE count, const char playerNames[][XUSER_NAME_SIZE]) +{ + EnterCriticalSection(&s_advertiseLock); + memset(s_advertiseData.playerNames, 0, sizeof(s_advertiseData.playerNames)); + s_advertiseData.playerCount = count; + for (int i = 0; i < count && i < 8; i++) + { + memcpy(s_advertiseData.playerNames[i], playerNames[i], XUSER_NAME_SIZE); + } + LeaveCriticalSection(&s_advertiseLock); +} + void WinsockNetLayer::UpdateAdvertiseJoinable(bool joinable) { EnterCriticalSection(&s_advertiseLock); @@ -1028,16 +1286,18 @@ void WinsockNetLayer::StopDiscovery() std::vector WinsockNetLayer::GetDiscoveredSessions() { std::vector result; - EnterCriticalSection(&s_discoveryLock); - result = s_discoveredSessions; - LeaveCriticalSection(&s_discoveryLock); + if (TryEnterCriticalSection(&s_discoveryLock)) + { + result = s_discoveredSessions; + LeaveCriticalSection(&s_discoveryLock); + } return result; } int WinsockNetLayer::DiscoveryThreadProc(LPVOID param) { app.DebugPrintf("Discovery thread started\n"); - char recvBuf[512]; + char recvBuf[1024]; while (s_discovering) { @@ -1111,6 +1371,7 @@ int WinsockNetLayer::DiscoveryThreadProc(LPVOID param) s_discoveredSessions[i].subTexturePackId = broadcast->subTexturePackId; s_discoveredSessions[i].isJoinable = (broadcast->isJoinable != 0); s_discoveredSessions[i].lastSeenTick = now; + memcpy(s_discoveredSessions[i].playerNames, broadcast->playerNames, sizeof(broadcast->playerNames)); found = true; break; } @@ -1137,6 +1398,7 @@ int WinsockNetLayer::DiscoveryThreadProc(LPVOID param) session.subTexturePackId = broadcast->subTexturePackId; session.isJoinable = (broadcast->isJoinable != 0); session.lastSeenTick = now; + memcpy(session.playerNames, broadcast->playerNames, sizeof(broadcast->playerNames)); s_discoveredSessions.push_back(session); app.DebugPrintf("LAN: Discovered game \"%ls\" at %s:%d\n", diff --git a/Minecraft.Client/Common/Network/WinsockNetLayer.h b/Minecraft.Client/Common/Network/WinsockNetLayer.h index 4ed26bc1..20c31fc0 100644 --- a/Minecraft.Client/Common/Network/WinsockNetLayer.h +++ b/Minecraft.Client/Common/Network/WinsockNetLayer.h @@ -4,6 +4,7 @@ #include #include #elif defined _XBOX +#include #include #include #elif defined __PS3__ @@ -15,6 +16,8 @@ #include #include #include +#include +#include #endif #include @@ -27,6 +30,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 @@ -50,6 +54,7 @@ struct Win64LANBroadcast DWORD texturePackParentId; BYTE subTexturePackId; BYTE isJoinable; + char playerNames[8][XUSER_NAME_SIZE]; }; #pragma pack(pop) @@ -66,6 +71,7 @@ struct Win64LANSession unsigned char subTexturePackId; bool isJoinable; DWORD lastSeenTick; + char playerNames[8][XUSER_NAME_SIZE]; }; struct Win64RemoteConnection @@ -101,11 +107,13 @@ 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(); static void UpdateAdvertisePlayerCount(BYTE count); static void UpdateAdvertiseJoinable(bool joinable); + static void UpdateAdvertisePlayerNames(BYTE count, const char playerNames[][XUSER_NAME_SIZE]); static bool StartDiscovery(); static void StopDiscovery(); diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp index 5abfb56f..4892b0ab 100644 --- a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp @@ -105,6 +105,21 @@ void UIScene_JoinMenu::tick() break; } } +#elif defined(_WINDOWS64) || defined(DISABLE_PSN) + for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ ) + { + if( m_selectedSession->data.players[i] != 0 && m_selectedSession->data.szPlayers[i][0] != 0 ) + { + string playerName(m_selectedSession->data.szPlayers[i], XUSER_NAME_SIZE); + size_t end = playerName.find('\0'); + if (end != string::npos) playerName.resize(end); + m_buttonListPlayers.addItem(playerName); + } + else + { + break; + } + } #endif m_labelLabels[eLabel_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY)); @@ -601,6 +616,30 @@ void UIScene_JoinMenu::handleTimerComplete(int id) playersList.SetCurSel(selectedIndex); } #endif +#if defined(_WINDOWS64) || defined(DISABLE_PSN) + { + bool success = g_NetworkManager.GetGameSessionInfo(m_iPad, m_selectedSession->sessionId, m_selectedSession); + if (success) + { + m_buttonListPlayers.clearList(); + for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) + { + if (m_selectedSession->data.players[i] != 0 && m_selectedSession->data.szPlayers[i][0] != 0) + { + string playerName(m_selectedSession->data.szPlayers[i], XUSER_NAME_SIZE); + size_t end = playerName.find('\0'); + if (end != string::npos) playerName.resize(end); + m_buttonListPlayers.addItem(playerName); + } + else + { + break; + } + } + } + } +#endif + addTimer(UPDATE_PLAYERS_TIMER_ID, UPDATE_PLAYERS_TIMER_TIME); } break; }; diff --git a/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp index 767921ab..5c5fca69 100644 --- a/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SignEntryMenu.cpp @@ -46,6 +46,7 @@ UIScene_SignEntryMenu::UIScene_SignEntryMenu(int iPad, void *_initData, UILayer m_signRows[i].SetTitleAndText(IDS_SIGN_TITLE,IDS_SIGN_TITLE_TEXT); #endif m_textInputLines[i].init(m_sign->GetMessage(i).c_str(), i); + m_textInputLines[i].SetCharLimit(15); } parentLayer->addComponent(iPad,eUIComponent_MenuBackground); @@ -150,6 +151,7 @@ int UIScene_SignEntryMenu::KeyboardCompleteCallback(LPVOID lpParam,bool bRes) uint16_t pchText[128]; ZeroMemory(pchText, 128 * sizeof(uint16_t) ); InputManager.GetText(pchText); + pchText[15] = 0; pClass->m_textInputLines[pClass->m_iEditingLine].setLabel((wchar_t *)pchText); } return 0; diff --git a/Minecraft.Client/Extrax64Stubs.cpp b/Minecraft.Client/Extrax64Stubs.cpp index 3696c6ff..c999145d 100644 --- a/Minecraft.Client/Extrax64Stubs.cpp +++ b/Minecraft.Client/Extrax64Stubs.cpp @@ -178,7 +178,7 @@ void PIXSetMarkerDeprecated(int a, char *b, ...) {} bool IsEqualXUID(PlayerUID a, PlayerUID b) { -#if !defined(DISABLE_PSN) && defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) || defined(_DURANGO) +#if !defined(DISABLE_PSN) && defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__) || defined(_DURANGO) || defined(_WINDOWS64) || defined(_XBOX) return (a == b); #elif defined(DISABLE_PSN) && defined(__PS3__) return (a.XUID == b.XUID); @@ -464,13 +464,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; } @@ -478,7 +482,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; @@ -504,19 +508,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() { @@ -531,15 +537,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/PS3/PS3_PlayerUID.cpp b/Minecraft.Client/PS3/PS3_PlayerUID.cpp index 4a95a7fc..9b88beed 100644 --- a/Minecraft.Client/PS3/PS3_PlayerUID.cpp +++ b/Minecraft.Client/PS3/PS3_PlayerUID.cpp @@ -160,7 +160,7 @@ bool PlayerUID::isPrimaryUser() const /* only true if we're on the local machine - +#ifndef DISABLE_PSN GameSessionUID::GameSessionUID() { memset(this,0,sizeof(GameSessionUID)); @@ -194,4 +194,4 @@ GameSessionUID& GameSessionUID::operator=(const PlayerUID& rhs) m_bSignedIntoPSN = rhs.isSignedIntoPSN(); return *this; } - +#endif \ No newline at end of file diff --git a/Minecraft.Client/PS3/PS3_PlayerUID.h b/Minecraft.Client/PS3/PS3_PlayerUID.h index 73f0a482..8fff1e79 100644 --- a/Minecraft.Client/PS3/PS3_PlayerUID.h +++ b/Minecraft.Client/PS3/PS3_PlayerUID.h @@ -55,7 +55,7 @@ private: - +#ifndef DISABLE_PSN class GameSessionUID { char m_onlineID[SCE_NET_NP_ONLINEID_MAX_LENGTH]; @@ -74,3 +74,5 @@ public: int getQuadrant() const { return m_quadrant; } bool isSignedIntoPSN() const { return m_bSignedIntoPSN; } }; +#endif + diff --git a/Minecraft.Client/PlayerList.cpp b/Minecraft.Client/PlayerList.cpp index 21817080..4ff43f5f 100644 --- a/Minecraft.Client/PlayerList.cpp +++ b/Minecraft.Client/PlayerList.cpp @@ -108,7 +108,9 @@ void PlayerList::placeNewPlayer(Connection *connection, shared_ptr { NetworkPlayerXbox *nxp = (NetworkPlayerXbox *)networkPlayer; IQNetPlayer *qnp = nxp->GetQNetPlayer(); - wcsncpy(qnp->m_gamertag, player->name.c_str(), 32); + wcsncpy(qnp->m_gamertag, player->name.c_str(), 31); + qnp->m_gamertag[31] = L'\0'; + g_NetworkManager.UpdateAndSetGameSessionData(); } #endif diff --git a/Minecraft.Client/Windows64/Windows64_App.cpp b/Minecraft.Client/Windows64/Windows64_App.cpp index 0d1bd4ca..1530b628 100644 --- a/Minecraft.Client/Windows64/Windows64_App.cpp +++ b/Minecraft.Client/Windows64/Windows64_App.cpp @@ -26,6 +26,8 @@ void CConsoleMinecraftApp::StoreLaunchData() } void CConsoleMinecraftApp::ExitGame() { + extern HWND g_hWnd; + PostMessage(g_hWnd, WM_CLOSE, 0, 0); } void CConsoleMinecraftApp::FatalLoadError() { diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 24bbae9e..ecd036e1 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -17,6 +17,7 @@ #include "..\..\Minecraft.World\Vec3.h" #include "..\..\Minecraft.World\Level.h" #include "..\..\Minecraft.World\net.minecraft.world.level.tile.h" +#include "..\MultiplayerLocalPlayer.h" #include "..\ClientConnection.h" #include "..\User.h" @@ -261,7 +262,7 @@ HRESULT InitD3D( IDirect3DDevice9 **ppDevice, pd3dPP->EnableAutoDepthStencil = TRUE; pd3dPP->AutoDepthStencilFormat = D3DFMT_D24S8; pd3dPP->SwapEffect = D3DSWAPEFFECT_DISCARD; - pd3dPP->PresentationInterval = D3DPRESENT_INTERVAL_ONE; + pd3dPP->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //pd3dPP->Flags = D3DPRESENTFLAG_NO_LETTERBOX; //ERR[D3D]: Can't set D3DPRESENTFLAG_NO_LETTERBOX when wide-screen is enabled // in the launcher/dashboard. @@ -551,6 +552,8 @@ app.DebugPrintf("width: %d, height: %d\n", width, height); descDSView.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDSView.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSView.Texture2D.MipSlice = 0; + // when would this ever be a non-garbage value? + descDSView.Flags = 0; hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSView, &g_pDepthStencilView); diff --git a/Minecraft.World/x64headers/extraX64.h b/Minecraft.World/x64headers/extraX64.h index 783834d9..69d0b508 100644 --- a/Minecraft.World/x64headers/extraX64.h +++ b/Minecraft.World/x64headers/extraX64.h @@ -52,6 +52,7 @@ typedef SQRNetworkManager_Orbis::PresenceSyncInfo INVITE_INFO; typedef SQRNetworkManager::SessionID SessionID; typedef SQRNetworkManager::PresenceSyncInfo INVITE_INFO; #else +typedef ULONGLONG GameSessionUID; typedef ULONGLONG SessionID; class INVITE_INFO; #endif