From fccf64801209ec41793931519d52514cf7a99ab4 Mon Sep 17 00:00:00 2001 From: 552eden <552eden@gmail.com> Date: Wed, 5 Aug 2026 14:07:03 +0300 Subject: [PATCH] Finish fixing VITA networking. --- Minecraft.Client/ClientConnection.cpp | 4 +- .../Common/Network/NetworkSocketLayer.cpp | 58 +++++++++++++++++-- .../Common/Postbuilds/PSVita-postbuild.ps1 | 3 +- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index b3476836..962d0fae 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -1833,6 +1833,7 @@ void ClientConnection::handleEntityActionAtPosition(shared_ptr packet) { + app.DebugPrintf("ClientConnection::handlePreLogin ENTER (user %d)\n", m_userIndex); // printf("Client: handlePreLogin\n"); #if 1 // 4J - Check that we can play with all the players already in the game who have Friends-Only UGC set @@ -2287,7 +2288,8 @@ void ClientConnection::handlePreLogin(shared_ptr packet) } BOOL allAllowed, friendsAllowed; ProfileManager.AllowedPlayerCreatedContent(m_userIndex,true,&allAllowed,&friendsAllowed); - send( shared_ptr( new LoginPacket(minecraft->user->name, SharedConstants::NETWORK_PROTOCOL_VERSION, offlineXUID, onlineXUID, (allAllowed!=TRUE && friendsAllowed==TRUE), + app.DebugPrintf("ClientConnection::handlePreLogin SENDING LoginPacket (user %d)\n", m_userIndex); + send( shared_ptr( new LoginPacket(minecraft->user->name, SharedConstants::NETWORK_PROTOCOL_VERSION, offlineXUID, onlineXUID, (allAllowed!=TRUE && friendsAllowed==TRUE), packet->m_ugcPlayersVersion, app.GetPlayerSkinId(m_userIndex), app.GetPlayerCapeId(m_userIndex), ProfileManager.IsGuest( m_userIndex )))); if(!g_NetworkManager.IsHost() ) diff --git a/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp b/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp index 7e2f07fa..785a8d22 100644 --- a/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp +++ b/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp @@ -20,7 +20,8 @@ void terminate_networking() {}; #endif #if defined __PSVITA__ -int socket(int family, int type, int protocol) { return sceNetSocket(NULL, family, type, protocol); }; +// every sceNet sample names its sockets - NULL is not a documented value here +int socket(int family, int type, int protocol) { return sceNetSocket("minecraft", family, type, protocol); }; #endif C4JThread* NetworkSocketLayer::s_acceptThread = NULL; @@ -269,6 +270,9 @@ bool NetworkSocketLayer::HostGame(int port) SceNetSockaddrIn addr = {}; #else struct sockaddr_in addr = {}; +#endif +#ifdef __PSVITA__ + addr.sin_len = sizeof(addr); #endif addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); @@ -593,7 +597,7 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) struct sockaddr_in addr = {}; #endif -#if defined(__ORBIS__) +#if defined(__ORBIS__) || defined(__PSVITA__) addr.sin_len = sizeof(addr); #endif addr.sin_family = AF_INET; @@ -606,7 +610,7 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) app.DebugPrintf("inet_addr failed for %s:%d\n", ip, port); return false; } -#elif defined(__ORBIS__) +#elif defined(__ORBIS__) || defined(__PSVITA__) if (sceNetInetPton(SCE_NET_AF_INET, ip, &addr.sin_addr.s_addr) <= 0) { app.DebugPrintf("inet_addr failed for %s:%d\n", ip, port); @@ -653,7 +657,15 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) tv.tv_sec = connectTimeoutMs / 1000; tv.tv_usec = (connectTimeoutMs % 1000) * 1000; #else - SceNetId eid = sceNetEpollCreate(NULL, 0); + // like sceNetSocket, this takes a name and NULL is not a documented value + SceNetId eid = sceNetEpollCreate("minecraft-connect", 0); + if (eid < 0) + { + app.DebugPrintf("sceNetEpollCreate failed: 0x%08x\n", eid); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + continue; + } SceNetEpollEvent ev = {}; ev.events = SCE_NET_EPOLLOUT; ev.data.fd = s_hostConnectionSocket; @@ -673,6 +685,10 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) (outEvents[0].events & (SCE_NET_EPOLLERR | SCE_NET_EPOLLHUP))) #endif { +#ifdef __PSVITA__ + app.DebugPrintf("epoll wait=%d events=0x%x errno=0x%08x\n", + selectResult, selectResult > 0 ? outEvents[0].events : 0, sys_net_errno); +#endif 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; @@ -706,7 +722,14 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) setsockopt(s_hostConnectionSocket, SOL_SOCKET, SCE_NET_SO_NBIO, &blocking, sizeof(blocking)); #endif +#ifdef __PSVITA__ + // sceNet takes microseconds in an int, and 4 bytes is a valid size for it, + // so a plain 3000 silently sets a 3ms recv timeout instead of 3s. PS3/Orbis + // expect a timeval, so the same call just fails there and leaves recv blocking. + int recvTimeout = 3000 * 1000; +#else DWORD recvTimeout = 3000; +#endif setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&recvTimeout, sizeof(recvTimeout)); /* iResult = connect(s_hostConnectionSocket, (struct sockaddr*)&addr, sizeof(addr)); @@ -863,7 +886,13 @@ void NetworkSocketLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, un INetworkPlayer *pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId); INetworkPlayer *pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId); - if (pPlayerFrom == NULL || pPlayerTo == NULL) return; + if (pPlayerFrom == NULL || pPlayerTo == NULL) + { + // dropping here is silent and looks identical to the peer never sending + app.DebugPrintf("LAN: DROPPED %u bytes - from smallId=%d(%s) to smallId=%d(%s)\n", + dataSize, fromSmallId, pPlayerFrom ? "ok" : "NULL", toSmallId, pPlayerTo ? "ok" : "NULL"); + return; + } if (s_isHost) { @@ -1133,6 +1162,14 @@ int NetworkSocketLayer::ClientRecvThreadProc(LPVOID param) break; } + static int s_recvLogged = 0; + if (s_recvLogged < 20) + { + app.DebugPrintf("LAN: recv %d bytes from host (host=%d local=%d)\n", + packetSize, s_hostSmallId, s_localSmallId); + s_recvLogged++; + } + HandleDataReceived(s_hostSmallId, s_localSmallId, &recvBuf[0], packetSize); } @@ -1245,6 +1282,9 @@ int NetworkSocketLayer::AdvertiseThreadProc(LPVOID param) struct sockaddr_in broadcastAddr; #endif memset(&broadcastAddr, 0, sizeof(broadcastAddr)); +#ifdef __PSVITA__ + broadcastAddr.sin_len = sizeof(broadcastAddr); +#endif broadcastAddr.sin_family = AF_INET; broadcastAddr.sin_port = htons(NETWORK_LAN_DISCOVERY_PORT); broadcastAddr.sin_addr.s_addr = INADDR_BROADCAST; @@ -1350,6 +1390,10 @@ bool NetworkSocketLayer::StartDiscovery() struct sockaddr_in bindAddr; #endif memset(&bindAddr, 0, sizeof(bindAddr)); +#ifdef __PSVITA__ + // sceNet rejects a sockaddr whose sin_len is unset + bindAddr.sin_len = sizeof(bindAddr); +#endif bindAddr.sin_family = AF_INET; bindAddr.sin_port = htons(NETWORK_LAN_DISCOVERY_PORT); bindAddr.sin_addr.s_addr = INADDR_ANY; @@ -1384,6 +1428,10 @@ bool NetworkSocketLayer::StartDiscovery() timeout.tv_sec = 0; timeout.tv_usec = 500000; setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); +#elif defined __PSVITA__ + // sceNet wants microseconds in an int here + int timeout = 500000; + setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); #endif s_discovering = true; diff --git a/Minecraft.Client/Common/Postbuilds/PSVita-postbuild.ps1 b/Minecraft.Client/Common/Postbuilds/PSVita-postbuild.ps1 index aeabac4d..2e421af3 100644 --- a/Minecraft.Client/Common/Postbuilds/PSVita-postbuild.ps1 +++ b/Minecraft.Client/Common/Postbuilds/PSVita-postbuild.ps1 @@ -12,7 +12,8 @@ $directories = @( "PSVITA_GAME\Common\Media", "PSVITA_GAME\Common\res", "PSVITA_GAME\PSVita\Sound", - "PSVITA_GAME\PSVita\Tutorial" + "PSVITA_GAME\PSVita\Tutorial", + "PSVITA_GAME\savedata" ) foreach ($dir in $directories) {