From 4b0520c938d10fbcd6ce4dde7dce572a84d4fad3 Mon Sep 17 00:00:00 2001 From: NaN Date: Tue, 4 Aug 2026 22:49:46 +0000 Subject: [PATCH] fix PS4 networking support (#20) gonna mark this a WIP till i test more with large worlds and achievements issues i dont wanna break the PS3 and other builds by enabling it freely, ideally i can get it to work without it also i wanna remove the GetLocalIPv4Interfaces auto discovery feature i just did that cause i had so many local networks it got confusing, will remove on Final PR editReviewed-on: https://gitea.str1k3r.xyz/pieeebot/cafeberry/pulls/20 Co-authored-by: NaN --- .../Common/Network/NetworkSocketLayer.cpp | 17 ++++++ .../Common/Network/NetworkSocketLayer.h | 6 +- .../Common/Network/PlatformNetworkManager.cpp | 4 +- .../Common/UI/UIScene_JoinMenu.cpp | 58 ++++++++++++++----- .../Common/UI/UIScene_LoadOrJoinMenu.cpp | 23 +++++--- .../Common/UI/UIScene_MainMenu.cpp | 18 +++++- .../Orbis/OrbisExtras/OrbisStubs.cpp | 27 +++++---- Minecraft.Client/Orbis/Orbis_Minecraft.cpp | 1 + 8 files changed, 115 insertions(+), 39 deletions(-) diff --git a/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp b/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp index 9e45a79c..66d3ba31 100644 --- a/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp +++ b/Minecraft.Client/Common/Network/NetworkSocketLayer.cpp @@ -61,9 +61,16 @@ std::vector NetworkSocketLayer::s_freeSmallIds; static bool s_locksCreated = false; bool g_MultiplayerHost = false; +#if defined __ORBIS__ +// Orbis has direct lan networking so it can bypass psn account checks bool g_MultiplayerJoin = true; int g_MultiplayerPort = NETWORK_LAN_DEFAULT_PORT; +char g_MultiplayerIP[256] = ""; +#else +bool g_MultiplayerJoin = false; +int g_MultiplayerPort = NETWORK_LAN_DEFAULT_PORT; char g_MultiplayerIP[256] = "127.0.0.1"; +#endif bool NetworkSocketLayer::Initialize() { @@ -588,6 +595,9 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port) struct sockaddr_in addr = {}; #endif +#if defined(__ORBIS__) + addr.sin_len = sizeof(addr); +#endif addr.sin_family = AF_INET; addr.sin_port = htons((uint16_t)port); @@ -1336,8 +1346,15 @@ bool NetworkSocketLayer::StartDiscovery() return false; } #endif +#if defined _WINDOWS64 || defined _XBOX DWORD timeout = 500; setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); +#elif defined __PS3__ || defined __ORBIS__ + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); +#endif s_discovering = true; s_discoveryThread = new C4JThread(DiscoveryThreadProc, NULL, "DiscoveryThreadProc"); diff --git a/Minecraft.Client/Common/Network/NetworkSocketLayer.h b/Minecraft.Client/Common/Network/NetworkSocketLayer.h index 69eed69a..62da1eb9 100644 --- a/Minecraft.Client/Common/Network/NetworkSocketLayer.h +++ b/Minecraft.Client/Common/Network/NetworkSocketLayer.h @@ -47,8 +47,8 @@ typedef int SOCKET; typedef int SOCKET; #define INVALID_SOCKET -1 #define SO_NBIO SCE_NET_SO_NBIO -#define sys_net_errno sce_net_errno -#define SYS_NET_EINPROGRESS SCE_NET_EINPROGRESS +#define sys_net_errno errno +#define SYS_NET_EINPROGRESS EINPROGRESS #define socketselect select #define closesocket sceNetSocketClose #define socketclose sceNetSocketClose @@ -229,4 +229,4 @@ private: extern bool g_MultiplayerHost; extern bool g_MultiplayerJoin; extern int g_MultiplayerPort; -extern char g_MultiplayerIP[256]; \ No newline at end of file +extern char g_MultiplayerIP[256]; diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp index 6b8040a4..5f6d43e1 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManager.cpp @@ -477,6 +477,8 @@ bool CPlatformNetworkManagerStub::_RunNetworkGame() { extern QNET_STATE _iQNetStubState; _iQNetStubState = QNET_STATE_GAME_PLAY; + if (m_pIQNet->IsHost()) + NetworkSocketLayer::UpdateAdvertiseJoinable(true); for (DWORD i = 0; i < IQNet::s_playerCount; i++) { @@ -698,7 +700,7 @@ void CPlatformNetworkManagerStub::SearchForGames() { std::vector lanSessions = NetworkSocketLayer::GetDiscoveredSessions(); - if (g_MultiplayerJoin) + if (g_MultiplayerJoin && g_MultiplayerIP[0] != '\0') { bool alreadyPresent = false; for (size_t i = 0; i < lanSessions.size(); i++) diff --git a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp index a107ed63..ec0fd459 100644 --- a/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_JoinMenu.cpp @@ -7,6 +7,7 @@ #include "..\..\MinecraftServer.h" #include "..\..\..\Minecraft.World\net.minecraft.world.level.h" #include "..\..\..\Minecraft.World\net.minecraft.world.h" +#include "..\..\Common\Network\NetworkSocketLayer.h" #define UPDATE_PLAYERS_TIMER_ID 0 #define UPDATE_PLAYERS_TIMER_TIME 30000 @@ -50,7 +51,6 @@ void UIScene_JoinMenu::tick() g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this); m_friendInfoRequestIssued = true; } - if( m_friendInfoUpdatedOK ) { m_friendInfoUpdatedOK = false; @@ -368,6 +368,12 @@ void UIScene_JoinMenu::checkPrivilegeCallback(LPVOID lpParam, bool hasPrivilege, void UIScene_JoinMenu::StartSharedLaunchFlow() { + const bool bManualJoin = (g_MultiplayerJoin == true); + if (bManualJoin) + { + JoinGame(this); + return; + } #if defined DISABLE_PSN JoinGame(this); #else @@ -421,6 +427,12 @@ int UIScene_JoinMenu::StartGame_SignInReturned(void *pParam,bool bContinue, int // Shared function to join the game that is the same whether we used the sign-in UI or not void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) { + if (pClass == NULL) + { + return; + } + const bool bManualJoin = (g_MultiplayerJoin == true); + DWORD dwSignedInUsers = 0; bool noPrivileges = false; DWORD dwLocalUsersMask = 0; @@ -428,10 +440,14 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) int iPadNotSignedInLive = -1; ProfileManager.SetLockedProfile(0); // TEMP! + if (bManualJoin) + { + isSignedInLive = true; + } // If we're in SD mode, then only the primary player gets to play if (app.IsLocalMultiplayerAvailable()) - { + { for(unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) { if(ProfileManager.IsSignedIn(index)) @@ -442,7 +458,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) iPadNotSignedInLive = index; } - if( !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; + if( !bManualJoin && !ProfileManager.AllowedToPlayMultiplayer(index) ) noPrivileges = true; dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(index); isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(index); } @@ -452,7 +468,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) { if(ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) { - if( !ProfileManager.AllowedToPlayMultiplayer(ProfileManager.GetPrimaryPad()) ) noPrivileges = true; + if( !bManualJoin && !ProfileManager.AllowedToPlayMultiplayer(ProfileManager.GetPrimaryPad()) ) noPrivileges = true; dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad()); #ifndef DISABLE_PSN @@ -467,7 +483,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) } // If this is an online game but not all players are signed in to Live, stop! - if (!isSignedInLive) + if (!bManualJoin && !isSignedInLive) { #ifdef __ORBIS__ // Check if PSN is unavailable because of age restriction @@ -497,14 +513,22 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) BOOL pccFriendsAllowed = TRUE; #if !defined(DISABLE_PSN) && (defined(__PS3__) || defined(__PSVITA__)) - if(isSignedInLive) + if(!bManualJoin && isSignedInLive) { ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&noUGC,NULL,NULL); } #else - ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); - if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + if(!bManualJoin) + { + ProfileManager.AllowedPlayerCreatedContent(ProfileManager.GetPrimaryPad(),false,&pccAllowed,&pccFriendsAllowed); + if(!pccAllowed && !pccFriendsAllowed) noUGC = true; + } #endif + if (bManualJoin) + { + noUGC = false; + noPrivileges = false; + } #ifdef __PSVITA__ @@ -534,13 +558,16 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad()); } else - { -#if defined(__ORBIS__) || defined(__PSVITA__) - bool chatRestricted = false; - ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); - if(chatRestricted) { - ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); +#if defined(__ORBIS__) || defined(__PSVITA__) + if(!bManualJoin) + { + bool chatRestricted = false; + ProfileManager.GetChatAndContentRestrictions(ProfileManager.GetPrimaryPad(),false,&chatRestricted,NULL,NULL); + if(chatRestricted) + { + ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() ); + } } #endif CGameNetworkManager::eJoinGameResult result = g_NetworkManager.JoinGame( pClass->m_selectedSession, dwLocalUsersMask ); @@ -550,6 +577,7 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) if( result != CGameNetworkManager::JOINGAME_SUCCESS ) { + pClass->m_bIgnoreInput = false; int exitReasonStringId = -1; switch(result) { @@ -643,4 +671,4 @@ void UIScene_JoinMenu::handleTimerComplete(int id) } break; }; -} \ No newline at end of file +} diff --git a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp index 94c8d8c2..aeeb871f 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp @@ -14,6 +14,7 @@ #include "..\..\TexturePackRepository.h" #include "..\..\TexturePack.h" #include "..\Network\SessionInfo.h" +#include "..\..\Common\Network\NetworkSocketLayer.h" #if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) #include "Common\Network\Sony\SonyHttp.h" #include "Common\Network\Sony\SonyRemoteStorage.h" @@ -1385,20 +1386,24 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) if( m_buttonListGames.getItemCount() > 0 && gameIndex < m_currentSessions->size() ) { #if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + const bool bManualJoin = (g_MultiplayerJoin == true); // 4J-PB - is the player allowed to join games? bool noUGC=false; bool bContentRestricted=false; - // we're online, since we are joining a game - ProfileManager.GetChatAndContentRestrictions(m_iPad,true,&noUGC,&bContentRestricted,NULL); + // A direct LAN join should probnot use PSN matchmaking or account privileges (nansess) + if(!bManualJoin) + { + ProfileManager.GetChatAndContentRestrictions(m_iPad,true,&noUGC,&bContentRestricted,NULL); + } #ifdef __ORBIS__ // 4J Stu - On PS4 we don't restrict playing multiplayer based on chat restriction, so remove this check noUGC = false; bool bPlayStationPlus=true; - int iPadWithNoPlaystationPlus=0; - bool isSignedInLive = true; + int iPadWithNoPlaystationPlus=-1; + bool isSignedInLive = true; int iPadNotSignedInLive = -1; for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { @@ -1414,6 +1419,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) if(ProfileManager.HasPlayStationPlus(i)==false) { bPlayStationPlus=false; + iPadWithNoPlaystationPlus = (int)i; break; } } @@ -1427,7 +1433,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) } #endif - if(noUGC) + if(!bManualJoin && noUGC) { // not allowed to join #ifndef __PSVITA__ @@ -1443,7 +1449,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) m_bIgnoreInput=false; return; } - else if(bContentRestricted) + else if(!bManualJoin && bContentRestricted) { ui.RequestContentRestrictedMessageBox(); @@ -1452,7 +1458,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) } #ifdef __ORBIS__ // If this is an online game but not all players are signed in to Live, stop! - else if (!isSignedInLive) + else if (!bManualJoin && !isSignedInLive) { UINT uiIDA[1]; uiIDA[0]=IDS_CONFIRM_OK; @@ -1471,7 +1477,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) } return; } - else if(bPlayStationPlus==false) + else if(!bManualJoin && bPlayStationPlus==false) { if(ProfileManager.RequestingPlaystationPlus(iPadWithNoPlaystationPlus)) @@ -1480,6 +1486,7 @@ void UIScene_LoadOrJoinMenu::CheckAndJoinGame(int gameIndex) UINT uiIDA[1]; uiIDA[0]=IDS_OK; ui.RequestAlertMessage(IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL); + m_bIgnoreInput=false; return; } diff --git a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp index f7ec3409..1a6f51d5 100644 --- a/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_MainMenu.cpp @@ -8,6 +8,7 @@ #include "UIScene_MainMenu.h" #ifdef __ORBIS__ #include +#include "..\..\Common\Network\NetworkSocketLayer.h" #endif Random *UIScene_MainMenu::random = new Random(); @@ -318,7 +319,16 @@ void UIScene_MainMenu::handlePress(F64 controlId, F64 childId) //CD - Added for audio ui.PlayUISFX(eSFX_Press); - ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + if(g_MultiplayerJoin) + { + // request only completes after the platform network timeout. + // this needs to be done before hand or else the PS4 crashes ill need to look more into this + CreateLoad_SignInReturned(this, true, primaryPad); + } + else + { + ProfileManager.RefreshChatAndContentRestrictions(RefreshChatAndContentRestrictionsReturned_PlayGame, this); + } } #else m_eAction=eAction_RunGame; @@ -1098,6 +1108,12 @@ void UIScene_MainMenu::RefreshChatAndContentRestrictionsReturned_PlayGame(void * int primaryPad = ProfileManager.GetPrimaryPad(); UIScene_MainMenu* pClass = (UIScene_MainMenu*)pParam; + const bool bManualJoin = (g_MultiplayerJoin == true); + if (bManualJoin) + { + CreateLoad_SignInReturned(pClass, true, primaryPad); + return; + } int (*signInReturnedFunc) (LPVOID,const bool, const int iPad) = NULL; diff --git a/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp b/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp index 1cc40be5..37924651 100644 --- a/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp +++ b/Minecraft.Client/Orbis/OrbisExtras/OrbisStubs.cpp @@ -619,7 +619,6 @@ DWORD GetFileAttributesA(LPCSTR lpFileName) SceFiosStat statData; if(sceFiosStatSync(NULL, filePath, &statData) != SCE_FIOS_OK) { - app.DebugPrintf("*** sceFiosStatSync Failed\n"); return -1; } if(statData.statFlags & SCE_FIOS_STATUS_DIRECTORY ) @@ -671,19 +670,25 @@ BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount) #ifndef _FINAL_BUILD -VOID OutputDebugStringW(LPCWSTR lpOutputString) -{ - wprintf(lpOutputString); +VOID OutputDebugStringW(LPCWSTR lpOutputString) +{ + if (lpOutputString != NULL) + wprintf(L"%ls", lpOutputString); + fflush(stdout); } -VOID OutputDebugStringA(LPCSTR lpOutputString) -{ - printf(lpOutputString); +VOID OutputDebugStringA(LPCSTR lpOutputString) +{ + if (lpOutputString != NULL) + printf("%s", lpOutputString); + fflush(stdout); } -VOID OutputDebugString(LPCSTR lpOutputString) -{ - printf(lpOutputString); +VOID OutputDebugString(LPCSTR lpOutputString) +{ + if (lpOutputString != NULL) + printf("%s", lpOutputString); + fflush(stdout); } #endif // _CONTENT_PACKAGE @@ -787,4 +792,4 @@ DWORD XGetLocale() DWORD XEnableGuestSignin(BOOL fEnable) { return 0; -} \ No newline at end of file +} diff --git a/Minecraft.Client/Orbis/Orbis_Minecraft.cpp b/Minecraft.Client/Orbis/Orbis_Minecraft.cpp index d2366fbd..a0d342b7 100644 --- a/Minecraft.Client/Orbis/Orbis_Minecraft.cpp +++ b/Minecraft.Client/Orbis/Orbis_Minecraft.cpp @@ -1060,6 +1060,7 @@ int main(int argc, const char *argv[] ) // ProfileManager for XN_LIVE_INVITE_ACCEPTED for QNet. g_NetworkManager.Initialise(); + NetworkSocketLayer::Initialize(); // debug switch to trial version ProfileManager.SetDebugFullOverride(true);