first commit

This commit is contained in:
murdle
2026-03-01 02:38:58 +02:00
commit 19250b9db4
19111 changed files with 4358159 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
#pragma once
using namespace std;
#include <vector>
#include <qnet.h>
#include "..\..\..\Minecraft.World\C4JThread.h"
#include "NetworkPlayerInterface.h"
#ifdef _XBOX
#include "..\..\Xbox\Network\PlatformNetworkManagerXbox.h"
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
#include "..\..\Common\Network\Sony\PlatformNetworkManagerSony.h"
#elif defined _DURANGO
#include "..\..\Durango\Network\PlatformNetworkManagerDurango.h"
#else
#include "PlatformNetworkManagerStub.h"
#endif
#include "SessionInfo.h"
#ifdef __ORBIS__
#include "..\..\Orbis\Network\PsPlusUpsellWrapper_Orbis.h"
#endif
class ClientConnection;
class Minecraft;
// This class implements the game-side interface to the networking system. As such, it is platform independent and may contain bits of game-side code where appropriate.
// It shouldn't ever reference any platform specifics of the network implementation (eg QNET), rather it should interface with an implementation of PlatformNetworkManager to
// provide this functionality.
class CGameNetworkManager
{
#ifdef _XBOX
friend class CPlatformNetworkManagerXbox;
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
friend class CPlatformNetworkManagerSony;
#elif defined _DURANGO
friend class CPlatformNetworkManagerDurango;
#else
friend class CPlatformNetworkManagerStub;
#endif
public:
CGameNetworkManager();
// Misc high level flow
typedef enum
{
JOINGAME_SUCCESS,
JOINGAME_FAIL_GENERAL,
JOINGAME_FAIL_SERVER_FULL
} eJoinGameResult;
void Initialise();
void Terminate();
void DoWork();
bool _RunNetworkGame(LPVOID lpParameter);
bool StartNetworkGame(Minecraft *minecraft, LPVOID lpParameter);
int CorrectErrorIDS(int IDS);
// Player management
static int GetLocalPlayerMask(int playerIndex);
int GetPlayerCount();
int GetOnlinePlayerCount();
bool AddLocalPlayerByUserIndex( int userIndex );
bool RemoveLocalPlayerByUserIndex( int userIndex );
INetworkPlayer *GetLocalPlayerByUserIndex(int userIndex );
INetworkPlayer *GetPlayerByIndex(int playerIndex);
INetworkPlayer *GetPlayerByXuid(PlayerUID xuid);
INetworkPlayer *GetPlayerBySmallId(unsigned char smallId);
wstring GetDisplayNameByGamertag(wstring gamertag);
INetworkPlayer *GetHostPlayer();
void RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam);
void UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam);
void HandleSignInChange();
bool ShouldMessageForFullSession();
// State management
bool IsInSession();
bool IsInGameplay();
bool IsLeavingGame();
bool IsReadyToPlayOrIdle();
// Hosting and game type
bool SetLocalGame(bool isLocal);
bool IsLocalGame();
void SetPrivateGame(bool isPrivate);
bool IsPrivateGame();
void HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0);
bool IsHost();
bool IsInStatsEnabledSession();
// Client session discovery
bool SessionHasSpace(unsigned int spaceRequired = 1);
vector<FriendSessionInfo *> *GetSessionList(int iPad, int localPlayers, bool partyOnly);
bool GetGameSessionInfo(int iPad, SessionID sessionId,FriendSessionInfo *foundSession);
void SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam );
void GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam );
void ForceFriendsSessionRefresh();
// Session joining and leaving
bool JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo);
eJoinGameResult JoinGame(FriendSessionInfo *searchResult, int localUsersMask);
static void CancelJoinGame(LPVOID lpParam); // Not part of the shared interface
bool LeaveGame(bool bMigrateHost);
static int JoinFromInvite_SignInReturned(void *pParam,bool bContinue, int iPad);
void UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving = NULL);
void SendInviteGUI(int iPad);
void ResetLeavingGame();
// Threads
bool IsNetworkThreadRunning();
static int RunNetworkGameThreadProc( void* lpParameter );
static int ServerThreadProc( void* lpParameter );
static int ExitAndJoinFromInviteThreadProc( void* lpParam );
#if (defined __PS3__) || (defined __ORBIS__) || (defined __PSVITA__)
static int MustSignInReturned_0(void *pParam,int iPad,C4JStorage::EMessageResult result);
static int PSNSignInReturned_0(void* pParam, bool bContinue, int iPad);
static int MustSignInReturned_1(void *pParam,int iPad,C4JStorage::EMessageResult result);
static int PSNSignInReturned_1(void* pParam, bool bContinue, int iPad);
#endif
static void _LeaveGame();
static int ChangeSessionTypeThreadProc( void* lpParam );
// System flags
void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
// Events
void ServerReadyCreate(bool create); // Create the signal (or set to NULL)
void ServerReady(); // Signal that we are ready
void ServerReadyWait(); // Wait for the signal
void ServerReadyDestroy(); // Destroy signal
bool ServerReadyValid(); // Is non-NULL
void ServerStoppedCreate(bool create); // Create the signal
void ServerStopped(); // Signal that we are ready
void ServerStoppedWait(); // Wait for the signal
void ServerStoppedDestroy(); // Destroy signal
bool ServerStoppedValid(); // Is non-NULL
#ifdef __PSVITA__
static bool usingAdhocMode();
static void setAdhocMode(bool bAdhoc);
static void startAdhocMatching();
#endif
// Debug output
wstring GatherStats();
void renderQueueMeter();
wstring GatherRTTStats();
// GUI debug output
// Used for debugging output
static const int messageQueue_length = 512;
static __int64 messageQueue[messageQueue_length];
static const int byteQueue_length = 512;
static __int64 byteQueue[byteQueue_length];
static int messageQueuePos;
// Methods called from PlatformNetworkManager
private:
void StateChange_AnyToHosting();
void StateChange_AnyToJoining();
void StateChange_JoiningToIdle(CPlatformNetworkManager::eJoinFailedReason reason);
void StateChange_AnyToStarting();
void StateChange_AnyToEnding(bool bStateWasPlaying);
void StateChange_AnyToIdle();
void CreateSocket( INetworkPlayer *pNetworkPlayer, bool localPlayer );
void CloseConnection( INetworkPlayer *pNetworkPlayer );
void PlayerJoining( INetworkPlayer *pNetworkPlayer );
void PlayerLeaving( INetworkPlayer *pNetworkPlayer );
void HostChanged();
void WriteStats( INetworkPlayer *pNetworkPlayer );
void GameInviteReceived( int userIndex, const INVITE_INFO *pInviteInfo);
void HandleInviteWhenInMenus( int userIndex, const INVITE_INFO *pInviteInfo);
void AddLocalPlayerFailed(int idx, bool serverFull = false);
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
void HandleDisconnect(bool bLostRoomOnly,bool bPSNSignOut);
#else
void HandleDisconnect(bool bLostRoomOnly);
#endif
int GetPrimaryPad();
int GetLockedProfile();
bool IsSignedInLive(int playerIdx);
bool AllowedToPlayMultiplayer(int playerIdx);
char *GetOnlineName(int playerIdx);
C4JThread::Event* m_hServerStoppedEvent;
C4JThread::Event* m_hServerReadyEvent;
bool m_bInitialised;
#ifdef _XBOX_ONE
public:
void SetFullSessionMessageOnNextSessionChange() { m_bFullSessionMessageOnNextSessionChange = true; }
#endif
private:
float m_lastPlayerEventTimeStart; // For telemetry
static CPlatformNetworkManager *s_pPlatformNetworkManager;
bool m_bNetworkThreadRunning;
int GetJoiningReadyPercentage();
bool m_bLastDisconnectWasLostRoomOnly;
bool m_bFullSessionMessageOnNextSessionChange;
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
bool m_bSignedOutofPSN;
#endif
#ifdef __ORBIS__
PsPlusUpsellWrapper *m_pUpsell;
INVITE_INFO *m_pInviteInfo;
int m_iPlayerInvited;
#endif
public:
#ifndef _XBOX
void FakeLocalPlayerJoined(); // Temporary method whilst we don't have real networking to make this happen
#endif
};
extern CGameNetworkManager g_NetworkManager;
#ifdef __PS3__
#undef __in
#define __out
#endif

View File

@@ -0,0 +1,31 @@
#pragma once
class Socket;
// This is the platform independent interface for dealing with players within a network game. This should be used directly by game code (and GameNetworkManager) rather than the platform-specific implementations.
class INetworkPlayer
{
public:
virtual ~INetworkPlayer() {}
virtual unsigned char GetSmallId() = 0;
virtual void SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority) = 0;
virtual bool IsSameSystem(INetworkPlayer *player) = 0;
virtual int GetSendQueueSizeBytes( INetworkPlayer *player, bool lowPriority ) = 0;
virtual int GetSendQueueSizeMessages( INetworkPlayer *player, bool lowPriority ) = 0;
virtual int GetCurrentRtt() = 0;
virtual bool IsHost() = 0;
virtual bool IsGuest() = 0;
virtual bool IsLocal() = 0;
virtual int GetSessionIndex() = 0;
virtual bool IsTalking() = 0;
virtual bool IsMutedByLocalUser(int userIndex) = 0;
virtual bool HasVoice() = 0;
virtual bool HasCamera() = 0;
virtual int GetUserIndex() = 0;
virtual void SetSocket(Socket *pSocket) = 0;
virtual Socket *GetSocket() = 0;
virtual const wchar_t *GetOnlineName() = 0;
virtual wstring GetDisplayName() = 0;
virtual PlayerUID GetUID() = 0;
};

View File

@@ -0,0 +1,126 @@
#pragma once
using namespace std;
#include <vector>
#include <qnet.h>
#include "..\..\..\Minecraft.World\C4JThread.h"
#include "NetworkPlayerInterface.h"
#include "SessionInfo.h"
class ClientConnection;
class Minecraft;
class CGameNetworkManager;
// This is the interface to be implemented by the platform-specific versions of the PlatformNetworkManagers. This API is used directly by GameNetworkManager so that
// it can remain as platform independent as possible.
// This value should be incremented if the server version changes, or the game session data changes
#define MINECRAFT_NET_VERSION VER_NETWORK
typedef struct _SearchForGamesData
{
DWORD sessionIDCount;
XSESSION_SEARCHRESULT_HEADER *searchBuffer;
XNQOS **ppQos;
SessionID *sessionIDList;
XOVERLAPPED *pOverlapped;
} SearchForGamesData;
class CPlatformNetworkManager
{
friend class CGameNetworkManager;
public:
typedef enum
{
JOIN_FAILED_SERVER_FULL,
JOIN_FAILED_INSUFFICIENT_PRIVILEGES,
JOIN_FAILED_NONSPECIFIC,
} eJoinFailedReason;
virtual bool Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize) = 0;
virtual void Terminate() = 0;
virtual int GetJoiningReadyPercentage() = 0;
virtual int CorrectErrorIDS(int IDS) = 0;
virtual void DoWork() = 0;
virtual int GetPlayerCount() = 0;
virtual int GetOnlinePlayerCount() = 0;
virtual int GetLocalPlayerMask(int playerIndex) = 0;
virtual bool AddLocalPlayerByUserIndex( int userIndex ) = 0;
virtual bool RemoveLocalPlayerByUserIndex( int userIndex ) = 0;
virtual INetworkPlayer *GetLocalPlayerByUserIndex( int userIndex ) = 0;
virtual INetworkPlayer *GetPlayerByIndex(int playerIndex) = 0;
virtual INetworkPlayer * GetPlayerByXuid(PlayerUID xuid) = 0;
virtual INetworkPlayer * GetPlayerBySmallId(unsigned char smallId) = 0;
virtual bool ShouldMessageForFullSession() = 0;
virtual INetworkPlayer *GetHostPlayer() = 0;
virtual bool IsHost() = 0;
virtual bool JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo) = 0;
virtual bool LeaveGame(bool bMigrateHost) = 0;
virtual bool IsInSession() = 0;
virtual bool IsInGameplay() = 0;
virtual bool IsReadyToPlayOrIdle() = 0;
virtual bool IsInStatsEnabledSession() = 0;
virtual bool SessionHasSpace(unsigned int spaceRequired = 1) = 0;
virtual void SendInviteGUI(int quadrant) = 0;
virtual bool IsAddingPlayer() = 0;
virtual void HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0) = 0;
virtual int JoinGame(FriendSessionInfo *searchResult, int dwLocalUsersMask, int dwPrimaryUserIndex ) = 0;
virtual void CancelJoinGame() {};
virtual bool SetLocalGame(bool isLocal) = 0;
virtual bool IsLocalGame() = 0;
virtual void SetPrivateGame(bool isPrivate) = 0;
virtual bool IsPrivateGame() = 0;
virtual bool IsLeavingGame() = 0;
virtual void ResetLeavingGame() = 0;
virtual void RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam) = 0;
virtual void UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam) = 0;
virtual void HandleSignInChange() = 0;
virtual bool _RunNetworkGame() = 0;
private:
virtual bool _LeaveGame(bool bMigrateHost, bool bLeaveRoom) = 0;
virtual void _HostGame(int usersMask, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0) = 0;
virtual bool _StartGame() = 0;
public:
virtual void UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving = NULL) = 0;
private:
virtual bool RemoveLocalPlayer( INetworkPlayer *pNetworkPlayer ) = 0;
public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index) = 0;
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index) = 0;
virtual wstring GatherStats() = 0;
virtual wstring GatherRTTStats() = 0;
private:
virtual void SetSessionTexturePackParentId( int id ) = 0;
virtual void SetSessionSubTexturePackId( int id ) = 0;
virtual void Notify(int ID, ULONG_PTR Param) = 0;
public:
virtual vector<FriendSessionInfo *> *GetSessionList(int iPad, int localPlayers, bool partyOnly) = 0;
virtual bool GetGameSessionInfo(int iPad, SessionID sessionId,FriendSessionInfo *foundSession) = 0;
virtual void SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam ) = 0;
virtual void GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam ) = 0;
virtual void ForceFriendsSessionRefresh() = 0;
#ifndef _XBOX
virtual void FakeLocalPlayerJoined() {}; // Temporary method whilst we don't have real networking to make this happen
#endif
#ifdef _DURANGO
virtual wstring GetDisplayNameByGamertag(wstring gamertag) = 0;
#endif
};

View File

@@ -0,0 +1,646 @@
#include "stdafx.h"
#include "..\..\..\Minecraft.World\Socket.h"
#include "..\..\..\Minecraft.World\StringHelpers.h"
#include "PlatformNetworkManagerStub.h"
#include "..\..\Xbox\Network\NetworkPlayerXbox.h" // TODO - stub version of this?
CPlatformNetworkManagerStub *g_pPlatformNetworkManager;
void CPlatformNetworkManagerStub::NotifyPlayerJoined(IQNetPlayer *pQNetPlayer )
{
const char * pszDescription;
// 4J Stu - We create a fake socket for every where that we need an INBOUND queue of game data. Outbound
// is all handled by QNet so we don't need that. Therefore each client player has one, and the host has one
// for each client player.
bool createFakeSocket = false;
bool localPlayer = false;
NetworkPlayerXbox *networkPlayer = (NetworkPlayerXbox *)addNetworkPlayer(pQNetPlayer);
if( pQNetPlayer->IsLocal() )
{
localPlayer = true;
if( pQNetPlayer->IsHost() )
{
pszDescription = "local host";
// 4J Stu - No socket for the localhost as it uses a special loopback queue
m_machineQNetPrimaryPlayers.push_back( pQNetPlayer );
}
else
{
pszDescription = "local";
// We need an inbound queue on all local players to receive data from the host
createFakeSocket = true;
}
}
else
{
if( pQNetPlayer->IsHost() )
{
pszDescription = "remote host";
}
else
{
pszDescription = "remote";
// If we are the host, then create a fake socket for every remote player
if( m_pIQNet->IsHost() )
{
createFakeSocket = true;
}
}
if( m_pIQNet->IsHost() && !m_bHostChanged )
{
// Do we already have a primary player for this system?
bool systemHasPrimaryPlayer = false;
for(AUTO_VAR(it, m_machineQNetPrimaryPlayers.begin()); it < m_machineQNetPrimaryPlayers.end(); ++it)
{
IQNetPlayer *pQNetPrimaryPlayer = *it;
if( pQNetPlayer->IsSameSystem(pQNetPrimaryPlayer) )
{
systemHasPrimaryPlayer = true;
break;
}
}
if( !systemHasPrimaryPlayer )
m_machineQNetPrimaryPlayers.push_back( pQNetPlayer );
}
}
g_NetworkManager.PlayerJoining( networkPlayer );
if( createFakeSocket == true && !m_bHostChanged )
{
g_NetworkManager.CreateSocket( networkPlayer, localPlayer );
}
app.DebugPrintf( "Player 0x%p \"%ls\" joined; %s; voice %i; camera %i.\n",
pQNetPlayer,
pQNetPlayer->GetGamertag(),
pszDescription,
(int) pQNetPlayer->HasVoice(),
(int) pQNetPlayer->HasCamera() );
if( m_pIQNet->IsHost() )
{
// 4J-PB - only the host should do this
// g_NetworkManager.UpdateAndSetGameSessionData();
SystemFlagAddPlayer( networkPlayer );
}
for( int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
if(playerChangedCallback[idx] != NULL)
playerChangedCallback[idx]( playerChangedCallbackParam[idx], networkPlayer, false );
}
if(m_pIQNet->GetState() == QNET_STATE_GAME_PLAY)
{
int localPlayerCount = 0;
for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
{
if( m_pIQNet->GetLocalPlayerByUserIndex(idx) != NULL ) ++localPlayerCount;
}
float appTime = app.getAppTime();
// Only record stats for the primary player here
m_lastPlayerEventTimeStart = appTime;
}
}
bool CPlatformNetworkManagerStub::Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize)
{
m_pGameNetworkManager = pGameNetworkManager;
m_flagIndexSize = flagIndexSize;
g_pPlatformNetworkManager = this;
for( int i = 0; i < XUSER_MAX_COUNT; i++ )
{
playerChangedCallback[ i ] = NULL;
}
m_bLeavingGame = false;
m_bLeaveGameOnTick = false;
m_bHostChanged = false;
m_bSearchResultsReady = false;
m_bSearchPending = false;
m_bIsOfflineGame = false;
m_pSearchParam = NULL;
m_SessionsUpdatedCallback = NULL;
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
m_searchResultsCount[i] = 0;
m_lastSearchStartTime[i] = 0;
// The results that will be filled in with the current search
m_pSearchResults[i] = NULL;
m_pQoSResult[i] = NULL;
m_pCurrentSearchResults[i] = NULL;
m_pCurrentQoSResult[i] = NULL;
m_currentSearchResultsCount[i] = 0;
}
// Success!
return true;
}
void CPlatformNetworkManagerStub::Terminate()
{
}
int CPlatformNetworkManagerStub::GetJoiningReadyPercentage()
{
return 100;
}
int CPlatformNetworkManagerStub::CorrectErrorIDS(int IDS)
{
return IDS;
}
bool CPlatformNetworkManagerStub::isSystemPrimaryPlayer(IQNetPlayer *pQNetPlayer)
{
return true;
}
// We call this twice a frame, either side of the render call so is a good place to "tick" things
void CPlatformNetworkManagerStub::DoWork()
{
}
int CPlatformNetworkManagerStub::GetPlayerCount()
{
return m_pIQNet->GetPlayerCount();
}
bool CPlatformNetworkManagerStub::ShouldMessageForFullSession()
{
return false;
}
int CPlatformNetworkManagerStub::GetOnlinePlayerCount()
{
return 1;
}
int CPlatformNetworkManagerStub::GetLocalPlayerMask(int playerIndex)
{
return 1 << playerIndex;
}
bool CPlatformNetworkManagerStub::AddLocalPlayerByUserIndex( int userIndex )
{
NotifyPlayerJoined(m_pIQNet->GetLocalPlayerByUserIndex(userIndex));
return ( m_pIQNet->AddLocalPlayerByUserIndex(userIndex) == S_OK );
}
bool CPlatformNetworkManagerStub::RemoveLocalPlayerByUserIndex( int userIndex )
{
return true;
}
bool CPlatformNetworkManagerStub::IsInStatsEnabledSession()
{
return true;
}
bool CPlatformNetworkManagerStub::SessionHasSpace(unsigned int spaceRequired /*= 1*/)
{
return true;
}
void CPlatformNetworkManagerStub::SendInviteGUI(int quadrant)
{
}
bool CPlatformNetworkManagerStub::IsAddingPlayer()
{
return false;
}
bool CPlatformNetworkManagerStub::LeaveGame(bool bMigrateHost)
{
if( m_bLeavingGame ) return true;
m_bLeavingGame = true;
// If we are the host wait for the game server to end
if(m_pIQNet->IsHost() && g_NetworkManager.ServerStoppedValid())
{
m_pIQNet->EndGame();
g_NetworkManager.ServerStoppedWait();
g_NetworkManager.ServerStoppedDestroy();
}
return true;
}
bool CPlatformNetworkManagerStub::_LeaveGame(bool bMigrateHost, bool bLeaveRoom)
{
return true;
}
void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots /*= MINECRAFT_NET_MAX_PLAYERS*/, unsigned char privateSlots /*= 0*/)
{
// #ifdef _XBOX
// 4J Stu - We probably did this earlier as well, but just to be sure!
SetLocalGame( !bOnlineGame );
SetPrivateGame( bIsPrivate );
SystemFlagReset();
// Make sure that the Primary Pad is in by default
localUsersMask |= GetLocalPlayerMask( g_NetworkManager.GetPrimaryPad() );
m_bLeavingGame = false;
m_pIQNet->HostGame();
_HostGame( localUsersMask, publicSlots, privateSlots );
//#endif
}
void CPlatformNetworkManagerStub::_HostGame(int usersMask, unsigned char publicSlots /*= MINECRAFT_NET_MAX_PLAYERS*/, unsigned char privateSlots /*= 0*/)
{
}
bool CPlatformNetworkManagerStub::_StartGame()
{
return true;
}
int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo *searchResult, int localUsersMask, int primaryUserIndex)
{
return CGameNetworkManager::JOINGAME_SUCCESS;
}
bool CPlatformNetworkManagerStub::SetLocalGame(bool isLocal)
{
m_bIsOfflineGame = isLocal;
return true;
}
void CPlatformNetworkManagerStub::SetPrivateGame(bool isPrivate)
{
app.DebugPrintf("Setting as private game: %s\n", isPrivate ? "yes" : "no" );
m_bIsPrivateGame = isPrivate;
}
void CPlatformNetworkManagerStub::RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam)
{
playerChangedCallback[iPad] = callback;
playerChangedCallbackParam[iPad] = callbackParam;
}
void CPlatformNetworkManagerStub::UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam)
{
if(playerChangedCallbackParam[iPad] == callbackParam)
{
playerChangedCallback[iPad] = NULL;
playerChangedCallbackParam[iPad] = NULL;
}
}
void CPlatformNetworkManagerStub::HandleSignInChange()
{
return;
}
bool CPlatformNetworkManagerStub::_RunNetworkGame()
{
return true;
}
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);
}
int CPlatformNetworkManagerStub::RemovePlayerOnSocketClosedThreadProc( void* lpParam )
{
INetworkPlayer *pNetworkPlayer = (INetworkPlayer *)lpParam;
Socket *socket = pNetworkPlayer->GetSocket();
if( socket != NULL )
{
//printf("Waiting for socket closed event\n");
socket->m_socketClosedEvent->WaitForSignal(INFINITE);
//printf("Socket closed event has fired\n");
// 4J Stu - Clear our reference to this socket
pNetworkPlayer->SetSocket( NULL );
delete socket;
}
return g_pPlatformNetworkManager->RemoveLocalPlayer( pNetworkPlayer );
}
bool CPlatformNetworkManagerStub::RemoveLocalPlayer( INetworkPlayer *pNetworkPlayer )
{
return true;
}
CPlatformNetworkManagerStub::PlayerFlags::PlayerFlags(INetworkPlayer *pNetworkPlayer, unsigned int count)
{
// 4J Stu - Don't assert, just make it a multiple of 8! This count is calculated from a load of separate values,
// and makes tweaking world/render sizes a pain if we hit an assert here
count = (count + 8 - 1) & ~(8 - 1);
//assert( ( count % 8 ) == 0 );
this->m_pNetworkPlayer = pNetworkPlayer;
this->flags = new unsigned char [ count / 8 ];
memset( this->flags, 0, count / 8 );
this->count = count;
}
CPlatformNetworkManagerStub::PlayerFlags::~PlayerFlags()
{
delete [] flags;
}
// Add a player to the per system flag storage - if we've already got a player from that system, copy its flags over
void CPlatformNetworkManagerStub::SystemFlagAddPlayer(INetworkPlayer *pNetworkPlayer)
{
PlayerFlags *newPlayerFlags = new PlayerFlags( pNetworkPlayer, m_flagIndexSize);
// If any of our existing players are on the same system, then copy over flags from that one
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
memcpy( newPlayerFlags->flags, m_playerFlags[i]->flags, m_playerFlags[i]->count / 8 );
break;
}
}
m_playerFlags.push_back(newPlayerFlags);
}
// Remove a player from the per system flag storage - just maintains the m_playerFlags vector without any gaps in it
void CPlatformNetworkManagerStub::SystemFlagRemovePlayer(INetworkPlayer *pNetworkPlayer)
{
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( m_playerFlags[i]->m_pNetworkPlayer == pNetworkPlayer )
{
delete m_playerFlags[i];
m_playerFlags[i] = m_playerFlags.back();
m_playerFlags.pop_back();
return;
}
}
}
void CPlatformNetworkManagerStub::SystemFlagReset()
{
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
delete m_playerFlags[i];
}
m_playerFlags.clear();
}
// Set a per system flag - this is done by setting the flag on every player that shares that system
void CPlatformNetworkManagerStub::SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index)
{
if( ( index < 0 ) || ( index >= m_flagIndexSize ) ) return;
if( pNetworkPlayer == NULL ) return;
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( pNetworkPlayer->IsSameSystem(m_playerFlags[i]->m_pNetworkPlayer) )
{
m_playerFlags[i]->flags[ index / 8 ] |= ( 128 >> ( index % 8 ) );
}
}
}
// Get value of a per system flag - can be read from the flags of the passed in player as anything else sent to that
// system should also have been duplicated here
bool CPlatformNetworkManagerStub::SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index)
{
if( ( index < 0 ) || ( index >= m_flagIndexSize ) ) return false;
if( pNetworkPlayer == NULL )
{
return false;
}
for( unsigned int i = 0; i < m_playerFlags.size(); i++ )
{
if( m_playerFlags[i]->m_pNetworkPlayer == pNetworkPlayer )
{
return ( ( m_playerFlags[i]->flags[ index / 8 ] & ( 128 >> ( index % 8 ) ) ) != 0 );
}
}
return false;
}
wstring CPlatformNetworkManagerStub::GatherStats()
{
return L"";
}
wstring CPlatformNetworkManagerStub::GatherRTTStats()
{
wstring stats(L"Rtt: ");
wchar_t stat[32];
for(unsigned int i = 0; i < GetPlayerCount(); ++i)
{
IQNetPlayer *pQNetPlayer = ((NetworkPlayerXbox *)GetPlayerByIndex( i ))->GetQNetPlayer();
if(!pQNetPlayer->IsLocal())
{
ZeroMemory(stat,32*sizeof(WCHAR));
swprintf(stat, 32, L"%d: %d/", i, pQNetPlayer->GetCurrentRtt() );
stats.append(stat);
}
}
return stats;
}
void CPlatformNetworkManagerStub::TickSearch()
{
}
void CPlatformNetworkManagerStub::SearchForGames()
{
}
int CPlatformNetworkManagerStub::SearchForGamesThreadProc( void* lpParameter )
{
return 0;
}
void CPlatformNetworkManagerStub::SetSearchResultsReady(int resultCount)
{
m_bSearchResultsReady = true;
m_searchResultsCount[m_lastSearchPad] = resultCount;
}
vector<FriendSessionInfo *> *CPlatformNetworkManagerStub::GetSessionList(int iPad, int localPlayers, bool partyOnly)
{
vector<FriendSessionInfo *> *filteredList = new vector<FriendSessionInfo *>();;
return filteredList;
}
bool CPlatformNetworkManagerStub::GetGameSessionInfo(int iPad, SessionID sessionId, FriendSessionInfo *foundSessionInfo)
{
return false;
}
void CPlatformNetworkManagerStub::SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam )
{
m_SessionsUpdatedCallback = SessionsUpdatedCallback; m_pSearchParam = pSearchParam;
}
void CPlatformNetworkManagerStub::GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam )
{
FriendSessionUpdatedFn(true, pParam);
}
void CPlatformNetworkManagerStub::ForceFriendsSessionRefresh()
{
app.DebugPrintf("Resetting friends session search data\n");
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
m_searchResultsCount[i] = 0;
m_lastSearchStartTime[i] = 0;
delete m_pSearchResults[i];
m_pSearchResults[i] = NULL;
}
}
INetworkPlayer *CPlatformNetworkManagerStub::addNetworkPlayer(IQNetPlayer *pQNetPlayer)
{
NetworkPlayerXbox *pNetworkPlayer = new NetworkPlayerXbox(pQNetPlayer);
pQNetPlayer->SetCustomDataValue((ULONG_PTR)pNetworkPlayer);
currentNetworkPlayers.push_back( pNetworkPlayer );
return pNetworkPlayer;
}
void CPlatformNetworkManagerStub::removeNetworkPlayer(IQNetPlayer *pQNetPlayer)
{
INetworkPlayer *pNetworkPlayer = getNetworkPlayer(pQNetPlayer);
for( AUTO_VAR(it, currentNetworkPlayers.begin()); it != currentNetworkPlayers.end(); it++ )
{
if( *it == pNetworkPlayer )
{
currentNetworkPlayers.erase(it);
return;
}
}
}
INetworkPlayer *CPlatformNetworkManagerStub::getNetworkPlayer(IQNetPlayer *pQNetPlayer)
{
return pQNetPlayer ? (INetworkPlayer *)(pQNetPlayer->GetCustomDataValue()) : NULL;
}
INetworkPlayer *CPlatformNetworkManagerStub::GetLocalPlayerByUserIndex(int userIndex )
{
return getNetworkPlayer(m_pIQNet->GetLocalPlayerByUserIndex(userIndex));
}
INetworkPlayer *CPlatformNetworkManagerStub::GetPlayerByIndex(int playerIndex)
{
return getNetworkPlayer(m_pIQNet->GetPlayerByIndex(playerIndex));
}
INetworkPlayer * CPlatformNetworkManagerStub::GetPlayerByXuid(PlayerUID xuid)
{
return getNetworkPlayer( m_pIQNet->GetPlayerByXuid(xuid)) ;
}
INetworkPlayer * CPlatformNetworkManagerStub::GetPlayerBySmallId(unsigned char smallId)
{
return getNetworkPlayer(m_pIQNet->GetPlayerBySmallId(smallId));
}
INetworkPlayer *CPlatformNetworkManagerStub::GetHostPlayer()
{
return getNetworkPlayer(m_pIQNet->GetHostPlayer());
}
bool CPlatformNetworkManagerStub::IsHost()
{
return m_pIQNet->IsHost() && !m_bHostChanged;
}
bool CPlatformNetworkManagerStub::JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo)
{
return ( m_pIQNet->JoinGameFromInviteInfo( userIndex, userMask, pInviteInfo ) == S_OK);
}
void CPlatformNetworkManagerStub::SetSessionTexturePackParentId( int id )
{
m_hostGameSessionData.texturePackParentId = id;
}
void CPlatformNetworkManagerStub::SetSessionSubTexturePackId( int id )
{
m_hostGameSessionData.subTexturePackId = id;
}
void CPlatformNetworkManagerStub::Notify(int ID, ULONG_PTR Param)
{
}
bool CPlatformNetworkManagerStub::IsInSession()
{
return m_pIQNet->GetState() != QNET_STATE_IDLE;
}
bool CPlatformNetworkManagerStub::IsInGameplay()
{
return m_pIQNet->GetState() == QNET_STATE_GAME_PLAY;
}
bool CPlatformNetworkManagerStub::IsReadyToPlayOrIdle()
{
return true;
}

View File

@@ -0,0 +1,170 @@
#pragma once
using namespace std;
#include <vector>
#include "..\..\..\Minecraft.World\C4JThread.h"
#include "NetworkPlayerInterface.h"
#include "PlatformNetworkManagerInterface.h"
#include "SessionInfo.h"
class CPlatformNetworkManagerStub : public CPlatformNetworkManager
{
friend class CGameNetworkManager;
public:
virtual bool Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize);
virtual void Terminate();
virtual int GetJoiningReadyPercentage();
virtual int CorrectErrorIDS(int IDS);
virtual void DoWork();
virtual int GetPlayerCount();
virtual int GetOnlinePlayerCount();
virtual int GetLocalPlayerMask(int playerIndex);
virtual bool AddLocalPlayerByUserIndex( int userIndex );
virtual bool RemoveLocalPlayerByUserIndex( int userIndex );
virtual INetworkPlayer *GetLocalPlayerByUserIndex( int userIndex );
virtual INetworkPlayer *GetPlayerByIndex(int playerIndex);
virtual INetworkPlayer * GetPlayerByXuid(PlayerUID xuid);
virtual INetworkPlayer * GetPlayerBySmallId(unsigned char smallId);
virtual bool ShouldMessageForFullSession();
virtual INetworkPlayer *GetHostPlayer();
virtual bool IsHost();
virtual bool JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo);
virtual bool LeaveGame(bool bMigrateHost);
virtual bool IsInSession();
virtual bool IsInGameplay();
virtual bool IsReadyToPlayOrIdle();
virtual bool IsInStatsEnabledSession();
virtual bool SessionHasSpace(unsigned int spaceRequired = 1);
virtual void SendInviteGUI(int quadrant);
virtual bool IsAddingPlayer();
virtual void HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0);
virtual int JoinGame(FriendSessionInfo *searchResult, int localUsersMask, int primaryUserIndex );
virtual bool SetLocalGame(bool isLocal);
virtual bool IsLocalGame() { return m_bIsOfflineGame; }
virtual void SetPrivateGame(bool isPrivate);
virtual bool IsPrivateGame() { return m_bIsPrivateGame; }
virtual bool IsLeavingGame() { return m_bLeavingGame; }
virtual void ResetLeavingGame() { m_bLeavingGame = false; }
virtual void RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam);
virtual void UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam);
virtual void HandleSignInChange();
virtual bool _RunNetworkGame();
private:
bool isSystemPrimaryPlayer(IQNetPlayer *pQNetPlayer);
virtual bool _LeaveGame(bool bMigrateHost, bool bLeaveRoom);
virtual void _HostGame(int dwUsersMask, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0);
virtual bool _StartGame();
IQNet * m_pIQNet; // pointer to QNet interface
HANDLE m_notificationListener;
vector<IQNetPlayer *> m_machineQNetPrimaryPlayers; // collection of players that we deem to be the main one for that system
bool m_bLeavingGame;
bool m_bLeaveGameOnTick;
bool m_migrateHostOnLeave;
bool m_bHostChanged;
bool m_bIsOfflineGame;
bool m_bIsPrivateGame;
int m_flagIndexSize;
// This is only maintained by the host, and is not valid on client machines
GameSessionData m_hostGameSessionData;
CGameNetworkManager *m_pGameNetworkManager;
public:
virtual void UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving = NULL);
private:
// TODO 4J Stu - Do we need to be able to have more than one of these?
void (*playerChangedCallback[XUSER_MAX_COUNT])(void *callbackParam, INetworkPlayer *pPlayer, bool leaving);
void *playerChangedCallbackParam[XUSER_MAX_COUNT];
static int RemovePlayerOnSocketClosedThreadProc( void* lpParam );
virtual bool RemoveLocalPlayer( INetworkPlayer *pNetworkPlayer );
// Things for handling per-system flags
class PlayerFlags
{
public:
INetworkPlayer *m_pNetworkPlayer;
unsigned char *flags;
unsigned int count;
PlayerFlags(INetworkPlayer *pNetworkPlayer, unsigned int count);
~PlayerFlags();
};
vector<PlayerFlags *> m_playerFlags;
void SystemFlagAddPlayer(INetworkPlayer *pNetworkPlayer);
void SystemFlagRemovePlayer(INetworkPlayer *pNetworkPlayer);
void SystemFlagReset();
public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
// For telemetry
private:
float m_lastPlayerEventTimeStart;
public:
wstring GatherStats();
wstring GatherRTTStats();
private:
vector<FriendSessionInfo *> friendsSessions[XUSER_MAX_COUNT];
int m_searchResultsCount[XUSER_MAX_COUNT];
int m_lastSearchStartTime[XUSER_MAX_COUNT];
// The results that will be filled in with the current search
XSESSION_SEARCHRESULT_HEADER *m_pSearchResults[XUSER_MAX_COUNT];
XNQOS *m_pQoSResult[XUSER_MAX_COUNT];
// The results from the previous search, which are currently displayed in the game
XSESSION_SEARCHRESULT_HEADER *m_pCurrentSearchResults[XUSER_MAX_COUNT];
XNQOS *m_pCurrentQoSResult[XUSER_MAX_COUNT];
int m_currentSearchResultsCount[XUSER_MAX_COUNT];
int m_lastSearchPad;
bool m_bSearchResultsReady;
bool m_bSearchPending;
LPVOID m_pSearchParam;
void (*m_SessionsUpdatedCallback)(LPVOID pParam);
C4JThread* m_SearchingThread;
void TickSearch();
void SearchForGames();
static int SearchForGamesThreadProc( void* lpParameter );
void SetSearchResultsReady(int resultCount = 0);
vector<INetworkPlayer *>currentNetworkPlayers;
INetworkPlayer *addNetworkPlayer(IQNetPlayer *pQNetPlayer);
void removeNetworkPlayer(IQNetPlayer *pQNetPlayer);
static INetworkPlayer *getNetworkPlayer(IQNetPlayer *pQNetPlayer);
virtual void SetSessionTexturePackParentId( int id );
virtual void SetSessionSubTexturePackId( int id );
virtual void Notify(int ID, ULONG_PTR Param);
public:
virtual vector<FriendSessionInfo *> *GetSessionList(int iPad, int localPlayers, bool partyOnly);
virtual bool GetGameSessionInfo(int iPad, SessionID sessionId,FriendSessionInfo *foundSession);
virtual void SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam );
virtual void GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam );
virtual void ForceFriendsSessionRefresh();
private:
void NotifyPlayerJoined( IQNetPlayer *pQNetPlayer );
#ifndef _XBOX
void FakeLocalPlayerJoined() { NotifyPlayerJoined(m_pIQNet->GetLocalPlayerByUserIndex(0)); }
#endif
};

View File

@@ -0,0 +1,113 @@
#pragma once
#if defined(__PS3__) || defined(__ORBIS__)
#include "..\..\Common\Network\Sony\SQRNetworkManager.h"
#endif
// A struct that we store in the QoS data when we are hosting the session. Max size 1020 bytes.
#ifdef _XBOX
typedef struct _GameSessionData
{
unsigned short netVersion; // 2 bytes
char hostName[XUSER_NAME_SIZE]; // 16 bytes ( 16*1 )
GameSessionUID hostPlayerUID; // 8 bytes ( 8*1 ) on xbox, 24 bytes on PS3
GameSessionUID players[MINECRAFT_NET_MAX_PLAYERS]; // 64 bytes ( 8*8 ) on xbox, 192 ( 24*8) on PS3
char szPlayers[MINECRAFT_NET_MAX_PLAYERS][XUSER_NAME_SIZE]; // 128 bytes ( 8*16)
unsigned int m_uiGameHostSettings; // 4 bytes
unsigned int texturePackParentId; // 4 bytes
unsigned char subTexturePackId; // 1 byte
bool isJoinable; // 1 byte
_GameSessionData()
{
netVersion = 0;
memset(hostName,0,XUSER_NAME_SIZE);
memset(players,0,MINECRAFT_NET_MAX_PLAYERS*sizeof(players[0]));
memset(szPlayers,0,MINECRAFT_NET_MAX_PLAYERS*XUSER_NAME_SIZE);
isJoinable = true;
m_uiGameHostSettings = 0;
texturePackParentId = 0;
subTexturePackId = 0;
}
} GameSessionData;
#elif defined __PS3__ || defined __ORBIS__ || defined(__PSVITA__)
typedef struct _GameSessionData
{
unsigned short netVersion; // 2 bytes
GameSessionUID hostPlayerUID; // 8 bytes ( 8*1 ) on xbox, 24 bytes on PS3
GameSessionUID players[MINECRAFT_NET_MAX_PLAYERS]; // 64 bytes ( 8*8 ) on xbox, 192 ( 24*8) on PS3
unsigned int m_uiGameHostSettings; // 4 bytes
unsigned int texturePackParentId; // 4 bytes
unsigned char subTexturePackId; // 1 byte
bool isJoinable; // 1 byte
unsigned char playerCount; // 1 byte
bool isReadyToJoin; // 1 byte
_GameSessionData()
{
netVersion = 0;
memset(players,0,MINECRAFT_NET_MAX_PLAYERS*sizeof(players[0]));
isJoinable = true;
m_uiGameHostSettings = 0;
texturePackParentId = 0;
subTexturePackId = 0;
playerCount = 0;
isReadyToJoin = false;
}
} GameSessionData;
#else
typedef struct _GameSessionData
{
unsigned short netVersion; // 2 bytes
unsigned int m_uiGameHostSettings; // 4 bytes
unsigned int texturePackParentId; // 4 bytes
unsigned char subTexturePackId; // 1 byte
bool isReadyToJoin; // 1 byte
_GameSessionData()
{
netVersion = 0;
m_uiGameHostSettings = 0;
texturePackParentId = 0;
subTexturePackId = 0;
}
} GameSessionData;
#endif
class FriendSessionInfo
{
public:
SessionID sessionId;
#ifdef _XBOX
XSESSION_SEARCHRESULT searchResult;
#elif defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
SQRNetworkManager::SessionSearchResult searchResult;
#elif defined(_DURANGO)
DQRNetworkManager::SessionSearchResult searchResult;
#endif
wchar_t *displayLabel;
unsigned char displayLabelLength;
unsigned char displayLabelViewableStartIndex;
GameSessionData data;
bool hasPartyMember;
FriendSessionInfo()
{
displayLabel = NULL;
displayLabelLength = 0;
displayLabelViewableStartIndex = 0;
hasPartyMember = false;
}
~FriendSessionInfo()
{
if(displayLabel!=NULL)
delete displayLabel;
}
};

View File

@@ -0,0 +1,114 @@
#include "stdafx.h"
#include "NetworkPlayerSony.h"
NetworkPlayerSony::NetworkPlayerSony(SQRNetworkPlayer *qnetPlayer)
{
m_sqrPlayer = qnetPlayer;
m_pSocket = NULL;
}
unsigned char NetworkPlayerSony::GetSmallId()
{
return m_sqrPlayer->GetSmallId();
}
void NetworkPlayerSony::SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority)
{
// TODO - handle priority
m_sqrPlayer->SendData( ((NetworkPlayerSony *)player)->m_sqrPlayer, pvData, dataSize );
}
bool NetworkPlayerSony::IsSameSystem(INetworkPlayer *player)
{
return m_sqrPlayer->IsSameSystem(((NetworkPlayerSony *)player)->m_sqrPlayer);
}
int NetworkPlayerSony::GetSendQueueSizeBytes( INetworkPlayer *player, bool lowPriority )
{
return 0; // TODO
}
int NetworkPlayerSony::GetSendQueueSizeMessages( INetworkPlayer *player, bool lowPriority )
{
return 0; // TODO
}
int NetworkPlayerSony::GetCurrentRtt()
{
return 0; // TODO
}
bool NetworkPlayerSony::IsHost()
{
return m_sqrPlayer->IsHost();
}
bool NetworkPlayerSony::IsGuest()
{
return false; // TODO
}
bool NetworkPlayerSony::IsLocal()
{
return m_sqrPlayer->IsLocal();
}
int NetworkPlayerSony::GetSessionIndex()
{
return m_sqrPlayer->GetSessionIndex();
}
bool NetworkPlayerSony::IsTalking()
{
return m_sqrPlayer->IsTalking();
}
bool NetworkPlayerSony::IsMutedByLocalUser(int userIndex)
{
return m_sqrPlayer->IsMutedByLocalUser(userIndex);
}
bool NetworkPlayerSony::HasVoice()
{
return m_sqrPlayer->HasVoice();
}
bool NetworkPlayerSony::HasCamera()
{
return false; // TODO
}
int NetworkPlayerSony::GetUserIndex()
{
return m_sqrPlayer->GetLocalPlayerIndex();
}
void NetworkPlayerSony::SetSocket(Socket *pSocket)
{
m_pSocket = pSocket;
}
Socket *NetworkPlayerSony::GetSocket()
{
return m_pSocket;
}
const wchar_t *NetworkPlayerSony::GetOnlineName()
{
return m_sqrPlayer->GetName();
}
wstring NetworkPlayerSony::GetDisplayName()
{
return m_sqrPlayer->GetName();
}
PlayerUID NetworkPlayerSony::GetUID()
{
return m_sqrPlayer->GetUID();
}
void NetworkPlayerSony::SetUID(PlayerUID UID)
{
m_sqrPlayer->SetUID(UID);
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include "..\..\Common\Network\NetworkPlayerInterface.h"
#include "SQRNetworkPlayer.h"
// This is an implementation of the INetworkPlayer interface, for Sony platforms. It effectively wraps the SQRNetworkPlayer class in a non-platform-specific way.
class NetworkPlayerSony : public INetworkPlayer
{
public:
// Common player interface
NetworkPlayerSony(SQRNetworkPlayer *sqrPlayer);
virtual unsigned char GetSmallId();
virtual void SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority);
virtual bool IsSameSystem(INetworkPlayer *player);
virtual int GetSendQueueSizeBytes( INetworkPlayer *player, bool lowPriority );
virtual int GetSendQueueSizeMessages( INetworkPlayer *player, bool lowPriority );
virtual int GetCurrentRtt();
virtual bool IsHost();
virtual bool IsGuest();
virtual bool IsLocal();
virtual int GetSessionIndex();
virtual bool IsTalking();
virtual bool IsMutedByLocalUser(int userIndex);
virtual bool HasVoice();
virtual bool HasCamera();
virtual int GetUserIndex();
virtual void SetSocket(Socket *pSocket);
virtual Socket *GetSocket();
virtual const wchar_t *GetOnlineName();
virtual wstring GetDisplayName();
virtual PlayerUID GetUID();
void SetUID(PlayerUID UID);
private:
SQRNetworkPlayer *m_sqrPlayer;
Socket *m_pSocket;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,187 @@
#pragma once
using namespace std;
#include <vector>
#include "..\..\..\Minecraft.World\C4JThread.h"
#include "..\..\Common\Network\NetworkPlayerInterface.h"
#include "..\..\Common\Network\PlatformNetworkManagerInterface.h"
#include "..\..\Common\Network\SessionInfo.h"
#include "SQRNetworkPlayer.h"
// This is how often we allow a search for new games
#define MINECRAFT_PS3ROOM_SEARCH_DELAY_MILLISECONDS 30000
// This is the Sony platform specific implementation of CPlatformNetworkManager. It is implemented using SQRNetworkManager/SQRNetworkPlayer. There shouldn't be any general game code in here,
// this class is for providing a bridge between the common game-side network implementation, and the lowest level platform specific libraries.
class CPlatformNetworkManagerSony : public CPlatformNetworkManager, ISQRNetworkManagerListener
{
friend class CGameNetworkManager;
public:
virtual bool Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize);
virtual void Terminate();
virtual int GetJoiningReadyPercentage();
virtual int CorrectErrorIDS(int IDS);
virtual void DoWork();
virtual int GetPlayerCount();
virtual int GetOnlinePlayerCount();
virtual int GetLocalPlayerMask(int playerIndex);
virtual bool AddLocalPlayerByUserIndex( int userIndex );
virtual bool RemoveLocalPlayerByUserIndex( int userIndex );
virtual INetworkPlayer *GetLocalPlayerByUserIndex( int userIndex );
virtual INetworkPlayer *GetPlayerByIndex(int playerIndex);
virtual INetworkPlayer * GetPlayerByXuid(PlayerUID xuid);
virtual INetworkPlayer * GetPlayerBySmallId(unsigned char smallId);
virtual bool ShouldMessageForFullSession();
virtual INetworkPlayer *GetHostPlayer();
virtual bool IsHost();
virtual bool JoinGameFromInviteInfo( int userIndex, int userMask, const INVITE_INFO *pInviteInfo);
virtual bool LeaveGame(bool bMigrateHost);
virtual bool IsInSession();
virtual bool IsInGameplay();
virtual bool IsReadyToPlayOrIdle();
virtual bool IsInStatsEnabledSession();
virtual bool SessionHasSpace(unsigned int spaceRequired = 1);
virtual void SendInviteGUI(int quadrant);
virtual bool IsAddingPlayer();
virtual void HostGame(int localUsersMask, bool bOnlineGame, bool bIsPrivate, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0);
virtual int JoinGame(FriendSessionInfo *searchResult, int localUsersMask, int primaryUserIndex );
virtual bool SetLocalGame(bool isLocal);
virtual bool IsLocalGame();
virtual void SetPrivateGame(bool isPrivate);
virtual bool IsPrivateGame();
virtual bool IsLeavingGame();
virtual void ResetLeavingGame();
virtual void RegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam);
virtual void UnRegisterPlayerChangedCallback(int iPad, void (*callback)(void *callbackParam, INetworkPlayer *pPlayer, bool leaving), void *callbackParam);
virtual void HandleSignInChange();
virtual bool _RunNetworkGame();
#ifdef __PSVITA__
bool usingAdhocMode() { return m_bUsingAdhocMode; }
bool setAdhocMode(bool bAdhoc);
void startAdhocMatching();
bool checkValidInviteData(const INVITE_INFO* pInviteInfo);
#endif
private:
bool isSystemPrimaryPlayer(SQRNetworkPlayer *pQNetPlayer);
virtual bool _LeaveGame(bool bMigrateHost, bool bLeaveRoom);
virtual void _HostGame(int dwUsersMask, unsigned char publicSlots = MINECRAFT_NET_MAX_PLAYERS, unsigned char privateSlots = 0);
virtual bool _StartGame();
#ifdef __PSVITA__
bool m_bUsingAdhocMode;
SQRNetworkManager_Vita* m_pSQRNet_Vita;
SQRNetworkManager_AdHoc_Vita* m_pSQRNet_Vita_Adhoc;
#endif
SQRNetworkManager * m_pSQRNet; // pointer to SQRNetworkManager interface
HANDLE m_notificationListener;
vector<SQRNetworkPlayer *> m_machineSQRPrimaryPlayers; // collection of players that we deem to be the main one for that system
bool m_bLeavingGame;
bool m_bLeaveGameOnTick;
bool m_migrateHostOnLeave;
bool m_bHostChanged;
bool m_bLeaveRoomWhenLeavingGame;
bool m_bIsOfflineGame;
bool m_bIsPrivateGame;
int m_flagIndexSize;
// This is only maintained by the host, and is not valid on client machines
GameSessionData m_hostGameSessionData;
CGameNetworkManager *m_pGameNetworkManager;
public:
virtual void UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving = NULL);
private:
// TODO 4J Stu - Do we need to be able to have more than one of these?
void (*playerChangedCallback[XUSER_MAX_COUNT])(void *callbackParam, INetworkPlayer *pPlayer, bool leaving);
void *playerChangedCallbackParam[XUSER_MAX_COUNT];
static int RemovePlayerOnSocketClosedThreadProc( void* lpParam );
virtual bool RemoveLocalPlayer( INetworkPlayer *pNetworkPlayer );
// Things for handling per-system flags
class PlayerFlags
{
public:
INetworkPlayer *m_pNetworkPlayer;
unsigned char *flags;
unsigned int count;
PlayerFlags(INetworkPlayer *pNetworkPlayer, unsigned int count);
~PlayerFlags();
};
vector<PlayerFlags *> m_playerFlags;
void SystemFlagAddPlayer(INetworkPlayer *pNetworkPlayer);
void SystemFlagRemovePlayer(INetworkPlayer *pNetworkPlayer);
void SystemFlagReset();
public:
virtual void SystemFlagSet(INetworkPlayer *pNetworkPlayer, int index);
virtual bool SystemFlagGet(INetworkPlayer *pNetworkPlayer, int index);
// For telemetry
private:
float m_lastPlayerEventTimeStart;
public:
wstring GatherStats();
wstring GatherRTTStats();
private:
vector<FriendSessionInfo *> friendsSessions;
int m_lastSearchStartTime;
// The results that will be filled in with the current search
int m_searchResultsCount;
SQRNetworkManager::SessionSearchResult *m_pSearchResults;
int m_lastSearchPad;
bool m_bSearchPending;
LPVOID m_pSearchParam;
void (*m_SessionsUpdatedCallback)(LPVOID pParam);
C4JThread* m_SearchingThread;
void TickSearch();
vector<INetworkPlayer *>currentNetworkPlayers;
INetworkPlayer *addNetworkPlayer(SQRNetworkPlayer *pSQRPlayer);
void removeNetworkPlayer(SQRNetworkPlayer *pSQRPlayer);
static INetworkPlayer *getNetworkPlayer(SQRNetworkPlayer *pSQRPlayer);
virtual void SetSessionTexturePackParentId( int id );
virtual void SetSessionSubTexturePackId( int id );
virtual void Notify(int ID, ULONG_PTR Param);
public:
virtual vector<FriendSessionInfo *> *GetSessionList(int iPad, int localPlayers, bool partyOnly);
virtual bool GetGameSessionInfo(int iPad, SessionID sessionId,FriendSessionInfo *foundSession);
virtual void SetSessionsUpdatedCallback( void (*SessionsUpdatedCallback)(LPVOID pParam), LPVOID pSearchParam );
virtual void GetFullFriendSessionInfo( FriendSessionInfo *foundSession, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam );
virtual void ForceFriendsSessionRefresh();
// ... and the new ones that have been converted to ISQRNetworkManagerListener
virtual void HandleDataReceived(SQRNetworkPlayer *playerFrom, SQRNetworkPlayer *playerTo, unsigned char *data, unsigned int dataSize);
virtual void HandlePlayerJoined(SQRNetworkPlayer *player);
virtual void HandlePlayerLeaving(SQRNetworkPlayer *player);
virtual void HandleStateChange(SQRNetworkManager::eSQRNetworkManagerState oldState, SQRNetworkManager::eSQRNetworkManagerState newState, bool idleReasonIsSessionFull);
virtual void HandleResyncPlayerRequest(SQRNetworkPlayer **aPlayers);
virtual void HandleAddLocalPlayerFailed(int idx);
virtual void HandleDisconnect(bool bLostRoomOnly,bool bPSNSignOut=false);
virtual void HandleInviteReceived( int userIndex, const SQRNetworkManager::PresenceSyncInfo *pInviteInfo);
static void SetSQRPresenceInfoFromExtData(SQRNetworkManager::PresenceSyncInfo *presence, void *pExtData, SceNpMatching2RoomId roomId, SceNpMatching2ServerId serverId);
static void MallocAndSetExtDataFromSQRPresenceInfo(void **pExtData, SQRNetworkManager::PresenceSyncInfo *presence);
};

View File

@@ -0,0 +1,10 @@
#include "stdafx.h"
#include "SQRNetworkManager.h"
bool SQRNetworkManager::s_safeToRespondToGameBootInvite = false;
void SQRNetworkManager::SafeToRespondToGameBootInvite()
{
s_safeToRespondToGameBootInvite = true;
}

View File

@@ -0,0 +1,313 @@
#pragma once
#include <np.h>
#ifdef __PS3__
#include <netex\libnetctl.h>
#include <netex\net.h>
#else
#include <libnetctl.h>
#include <net.h>
#include <np_toolkit.h>
#endif
#include <queue>
#include <unordered_map>
class SQRNetworkPlayer;
class ISQRNetworkManagerListener;
class SonyVoiceChat;
class C4JThread;
// This is the lowest level manager for providing network functionality on Sony platforms. This manages various network activities including the players within a gaming session.
// The game shouldn't directly use this class, it is here to provide functionality required by PlatformNetworkManagerSony.
class SQRNetworkManager
{
public:
static const int MAX_LOCAL_PLAYER_COUNT = XUSER_MAX_COUNT;
static const int MAX_ONLINE_PLAYER_COUNT = MINECRAFT_NET_MAX_PLAYERS;
static const int NP_POOL_SIZE = 128 * 1024;
protected:
friend class SQRNetworkPlayer;
friend class SonyVoiceChat;
static const int MAX_FRIENDS = 100;
#ifdef __PS3__
static const int RUDP_THREAD_PRIORITY = 999;
#else // __ORBIS_
static const int RUDP_THREAD_PRIORITY = 500;
#endif
static const int RUDP_THREAD_STACK_SIZE = 32878;
static const int MAX_SIMULTANEOUS_INVITES = 10;
// This class stores everything about a player that must be synchronised between machines. This syncing is carried out
// by the Matching2 lib by using internal room binary data (ie data that is only visible to current members of a room)
class PlayerSyncData
{
public:
PlayerUID m_UID; // Assigned by the associated player->GetUID()
SceNpMatching2RoomMemberId m_roomMemberId; // Assigned by Matching2 lib, we can use to indicate which machine this player belongs to (note - 16 bits)
unsigned char m_smallId; // Assigned by SQRNetworkManager, to attach a permanent id to this player (until we have to wrap round), to match a similar concept in qnet
unsigned char m_localIdx : 4; // Which local player (by controller index) this represents
unsigned char m_playerCount : 4;
};
class RoomSyncData
{
public:
PlayerSyncData players[MAX_ONLINE_PLAYER_COUNT];
void setPlayerCount(int c) { players[0].m_playerCount = c;}
int getPlayerCount() { return players[0].m_playerCount;}
};
public:
class PresenceSyncInfo
{
public:
GameSessionUID hostPlayerUID;
SceNpMatching2RoomId m_RoomId;
SceNpMatching2ServerId m_ServerId;
unsigned int texturePackParentId;
unsigned short netVersion;
unsigned char subTexturePackId;
bool inviteOnly;
};
// Externally exposed state. All internal states are mapped to one of these broader states.
typedef enum
{
SNM_STATE_INITIALISING,
SNM_STATE_INITIALISE_FAILED,
SNM_STATE_IDLE,
SNM_STATE_HOSTING,
SNM_STATE_JOINING,
SNM_STATE_STARTING,
SNM_STATE_PLAYING,
SNM_STATE_LEAVING,
SNM_STATE_ENDING,
} eSQRNetworkManagerState;
struct SessionID
{
SceNpMatching2RoomId m_RoomId;
SceNpMatching2ServerId m_ServerId;
};
struct SessionSearchResult
{
SceNpId m_NpId;
SessionID m_sessionId;
void *m_extData;
#ifdef __PSVITA__
SceNetInAddr m_netAddr;
#endif
};
protected:
// On initialisation, state should transition from SNM_INT_STATE_UNINITIALISED -> SNM_INT_STATE_SIGNING_IN -> SNM_INT_STATE_SIGNED_IN -> SNM_INT_STATE_STARTING_CONTEXT -> SNM_INT_STATE_IDLE.
// Error indicated if we transition at any point to SNM_INT_STATE_INITIALISE_FAILED.
// NOTE: If anything changes in here, then the mapping from internal -> external state needs to be updated (m_INTtoEXTStateMappings, defined in the cpp file)
typedef enum
{
SNM_INT_STATE_UNINITIALISED,
SNM_INT_STATE_SIGNING_IN,
SNM_INT_STATE_STARTING_CONTEXT,
SNM_INT_STATE_INITIALISE_FAILED,
SNM_INT_STATE_IDLE,
SNM_INT_STATE_IDLE_RECREATING_MATCHING_CONTEXT,
SNM_INT_STATE_HOSTING_STARTING_MATCHING_CONTEXT,
SNM_INT_STATE_HOSTING_SEARCHING_FOR_SERVER,
SNM_INT_STATE_HOSTING_SERVER_SEARCH_SERVER_ERROR,
SNM_INT_STATE_HOSTING_SERVER_FOUND,
SNM_INT_STATE_HOSTING_SERVER_SEARCH_CREATING_CONTEXT,
SNM_INT_STATE_HOSTING_SERVER_SEARCH_FAILED,
SNM_INT_STATE_HOSTING_CREATE_ROOM_SEARCHING_FOR_WORLD,
SNM_INT_STATE_HOSTING_CREATE_ROOM_WORLD_FOUND,
SNM_INT_STATE_HOSTING_CREATE_ROOM_CREATING_ROOM,
SNM_INT_STATE_HOSTING_CREATE_ROOM_SUCCESS,
SNM_INT_STATE_HOSTING_CREATE_ROOM_FAILED,
SNM_INT_STATE_HOSTING_CREATE_ROOM_RESTART_MATCHING_CONTEXT,
SNM_INT_STATE_HOSTING_WAITING_TO_PLAY,
SNM_INT_STATE_JOINING_STARTING_MATCHING_CONTEXT,
SNM_INT_STATE_JOINING_SEARCHING_FOR_SERVER,
SNM_INT_STATE_JOINING_SERVER_SEARCH_SERVER_ERROR,
SNM_INT_STATE_JOINING_SERVER_FOUND,
SNM_INT_STATE_JOINING_SERVER_SEARCH_CREATING_CONTEXT,
SNM_INT_STATE_JOINING_SERVER_SEARCH_FAILED,
SNM_INT_STATE_JOINING_JOIN_ROOM,
SNM_INT_STATE_JOINING_JOIN_ROOM_FAILED,
SNM_INT_STATE_JOINING_WAITING_FOR_LOCAL_PLAYERS,
SNM_INT_STATE_SERVER_DELETING_CONTEXT,
SNM_INT_STATE_STARTING,
SNM_INT_STATE_PLAYING,
SNM_INT_STATE_LEAVING,
SNM_INT_STATE_LEAVING_FAILED,
SNM_INT_STATE_ENDING,
SNM_INT_STATE_COUNT
} eSQRNetworkManagerInternalState;
typedef enum
{
SNM_FORCE_ERROR_NP2_INIT,
SNM_FORCE_ERROR_NET_INITIALIZE_NETWORK,
SNM_FORCE_ERROR_NET_CTL_INIT,
SNM_FORCE_ERROR_RUDP_INIT,
SNM_FORCE_ERROR_NET_START_DIALOG,
SNM_FORCE_ERROR_MATCHING2_INIT,
SNM_FORCE_ERROR_REGISTER_NP_CALLBACK,
SNM_FORCE_ERROR_GET_NPID,
SNM_FORCE_ERROR_CREATE_MATCHING_CONTEXT,
SNM_FORCE_ERROR_REGISTER_CALLBACKS,
SNM_FORCE_ERROR_CONTEXT_START_ASYNC,
SNM_FORCE_ERROR_SET_EXTERNAL_ROOM_DATA,
SNM_FORCE_ERROR_GET_FRIEND_LIST_ENTRY_COUNT,
SNM_FORCE_ERROR_GET_FRIEND_LIST_ENTRY,
SNM_FORCE_ERROR_GET_USER_INFO_LIST,
SNM_FORCE_ERROR_LEAVE_ROOM,
SNM_FORCE_ERROR_SET_ROOM_MEMBER_DATA_INTERNAL,
SNM_FORCE_ERROR_SET_ROOM_MEMBER_DATA_INTERNAL2,
SNM_FORCE_ERROR_CREATE_SERVER_CONTEXT,
SNM_FORCE_ERROR_CREATE_JOIN_ROOM,
SNM_FORCE_ERROR_GET_SERVER_INFO,
SNM_FORCE_ERROR_DELETE_SERVER_CONTEXT,
SNM_FORCE_ERROR_SETSOCKOPT_0,
SNM_FORCE_ERROR_SETSOCKOPT_1,
SNM_FORCE_ERROR_SETSOCKOPT_2,
SNM_FORCE_ERROR_SOCK_BIND,
SNM_FORCE_ERROR_CREATE_RUDP_CONTEXT,
SNM_FORCE_ERROR_RUDP_BIND,
SNM_FORCE_ERROR_RUDP_INIT2,
SNM_FORCE_ERROR_GET_ROOM_EXTERNAL_DATA,
SNM_FORCE_ERROR_GET_SERVER_INFO_DATA,
SNM_FORCE_ERROR_GET_WORLD_INFO_DATA,
SNM_FORCE_ERROR_GET_CREATE_JOIN_ROOM_DATA,
SNM_FORCE_ERROR_GET_USER_INFO_LIST_DATA,
SNM_FORCE_ERROR_GET_JOIN_ROOM_DATA,
SNM_FORCE_ERROR_GET_ROOM_MEMBER_DATA_INTERNAL,
SNM_FORCE_ERROR_GET_ROOM_EXTERNAL_DATA2,
SNM_FORCE_ERROR_CREATE_SERVER_CONTEXT_CALLBACK,
SNM_FORCE_ERROR_SET_ROOM_DATA_CALLBACK,
SNM_FORCE_ERROR_UPDATED_ROOM_DATA,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL1,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL2,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL3,
SNM_FORCE_ERROR_UPDATED_ROOM_MEMBER_DATA_INTERNAL4,
SNM_FORCE_ERROR_GET_WORLD_INFO_LIST,
SNM_FORCE_ERROR_JOIN_ROOM,
SNM_FORCE_ERROR_COUNT,
} eSQRForceError;
class StateChangeInfo
{
public:
eSQRNetworkManagerState m_oldState;
eSQRNetworkManagerState m_newState;
bool m_idleReasonIsSessionFull;
StateChangeInfo(eSQRNetworkManagerState oldState, eSQRNetworkManagerState newState,bool idleReasonIsSessionFull) : m_oldState(oldState), m_newState(newState), m_idleReasonIsSessionFull(idleReasonIsSessionFull) {}
};
std::queue<StateChangeInfo> m_stateChangeQueue;
CRITICAL_SECTION m_csStateChangeQueue;
CRITICAL_SECTION m_csMatching;
typedef enum
{
SNM_FRIEND_SEARCH_STATE_IDLE, // Idle - search result will be valid (although it may not have any entries)
SNM_FRIEND_SEARCH_STATE_GETTING_FRIEND_COUNT, // Getting count of friends in friend list
SNM_FRIEND_SEARCH_STATE_GETTING_FRIEND_INFO, // Getting presence/NpId info for each friend
} eSQRNetworkManagerFriendSearchState;
typedef void (*ServerContextValidCallback)(SQRNetworkManager *manager);
static bool s_safeToRespondToGameBootInvite;
public:
// General
virtual void Tick() = 0;
virtual void Initialise() = 0;
#ifdef __PSVITA__
virtual void UnInitialise() = 0; // to switch from PSN to Adhoc
virtual bool IsInitialised() = 0;
#endif
virtual void Terminate() = 0;
virtual eSQRNetworkManagerState GetState() = 0;
virtual bool IsHost() = 0;
virtual bool IsReadyToPlayOrIdle() = 0;
virtual bool IsInSession() = 0;
// Session management
virtual void CreateAndJoinRoom(int hostIndex, int localPlayerMask, void *extData, int extDataSize, bool offline) = 0;
virtual void UpdateExternalRoomData() = 0;
virtual bool FriendRoomManagerIsBusy() = 0;
virtual bool FriendRoomManagerSearch() = 0;
virtual bool FriendRoomManagerSearch2() = 0;
virtual int FriendRoomManagerGetCount() = 0;
virtual void FriendRoomManagerGetRoomInfo(int idx, SessionSearchResult *searchResult) = 0;
virtual bool JoinRoom(SessionSearchResult *searchResult, int localPlayerMask) = 0;
virtual bool JoinRoom(SceNpMatching2RoomId roomId, SceNpMatching2ServerId serverId, int localPlayerMask, const SQRNetworkManager::PresenceSyncInfo *presence) = 0;
virtual void StartGame() = 0;
virtual void LeaveRoom(bool bActuallyLeaveRoom) = 0;
virtual void EndGame() = 0;
virtual bool SessionHasSpace(int spaceRequired) = 0;
virtual bool AddLocalPlayerByUserIndex(int idx) = 0;
virtual bool RemoveLocalPlayerByUserIndex(int idx) = 0;
virtual void SendInviteGUI() = 0;
virtual void GetExtDataForRoom( SceNpMatching2RoomId roomId, void *extData, void (* FriendSessionUpdatedFn)(bool success, void *pParam), void *pParam ) = 0;
// Player retrieval
virtual int GetPlayerCount() = 0;
virtual int GetOnlinePlayerCount() = 0;
virtual SQRNetworkPlayer *GetPlayerByIndex(int idx) = 0;
virtual SQRNetworkPlayer *GetPlayerBySmallId(int idx) = 0;
virtual SQRNetworkPlayer *GetPlayerByXuid(PlayerUID xuid) = 0;
virtual SQRNetworkPlayer *GetLocalPlayerByUserIndex(int idx) = 0;
virtual SQRNetworkPlayer *GetHostPlayer() = 0;
virtual void SetPresenceDataStartHostingGame() = 0;
virtual int GetJoiningReadyPercentage() = 0;
virtual void LocalDataSend(SQRNetworkPlayer *playerFrom, SQRNetworkPlayer *playerTo, const void *data, unsigned int dataSize) = 0;
virtual int GetSessionIndex(SQRNetworkPlayer *player) = 0;
static void SafeToRespondToGameBootInvite();
};
// Class defining interface to be implemented for class that handles callbacks
class ISQRNetworkManagerListener
{
public:
virtual void HandleDataReceived(SQRNetworkPlayer *playerFrom, SQRNetworkPlayer *playerTo, unsigned char *data, unsigned int dataSize) = 0;
virtual void HandlePlayerJoined(SQRNetworkPlayer *player) = 0;
virtual void HandlePlayerLeaving(SQRNetworkPlayer *player) = 0;
virtual void HandleStateChange(SQRNetworkManager::eSQRNetworkManagerState oldState, SQRNetworkManager::eSQRNetworkManagerState newState, bool idleReasonIsSessionFull) = 0;
virtual void HandleResyncPlayerRequest(SQRNetworkPlayer **aPlayers) = 0;
virtual void HandleAddLocalPlayerFailed(int idx) = 0;
virtual void HandleDisconnect(bool bLostRoomOnly,bool bPSNSignOut=false) = 0;
virtual void HandleInviteReceived( int userIndex, const SQRNetworkManager::PresenceSyncInfo *pInviteInfo) = 0;
};

View File

@@ -0,0 +1,399 @@
#include "stdafx.h"
#include "SQRNetworkPlayer.h"
#ifdef __PS3__
#include <cell/rudp.h>
#include "PS3/Network/SonyVoiceChat.h"
#elif defined __ORBIS__
#include <rudp.h>
#include "Orbis/Network/SonyVoiceChat_Orbis.h"
#else // __PSVITA__
#include <rudp.h>
#include <adhoc_matching.h>
#include "PSVita/Network/SonyVoiceChat_Vita.h"
#endif
static const bool sc_verbose = false;
int SQRNetworkPlayer::GetSmallId()
{
return m_ISD.m_smallId;
}
wchar_t *SQRNetworkPlayer::GetName()
{
return m_name;
}
bool SQRNetworkPlayer::IsRemote()
{
return !IsLocal();
}
bool SQRNetworkPlayer::IsHost()
{
return (m_type == SNP_TYPE_HOST);
}
bool SQRNetworkPlayer::IsLocal()
{
// m_host determines whether this *machine* is hosting the game, not this player (which is determined by m_type)
if( m_host )
{
// If we are the hosting machine, then both the host & local players are local to this machine
return (m_type == SNP_TYPE_HOST) || (m_type == SNP_TYPE_LOCAL);
}
else
{
// Not hosting, just local players are actually physically local
return (m_type == SNP_TYPE_LOCAL) ;
}
}
int SQRNetworkPlayer::GetLocalPlayerIndex()
{
return m_localPlayerIdx;
}
bool SQRNetworkPlayer::IsSameSystem(SQRNetworkPlayer *other)
{
return (m_roomMemberId == other->m_roomMemberId);
}
uintptr_t SQRNetworkPlayer::GetCustomDataValue()
{
return m_customData;
}
void SQRNetworkPlayer::SetCustomDataValue(uintptr_t data)
{
m_customData = data;
}
SQRNetworkPlayer::SQRNetworkPlayer(SQRNetworkManager *manager, eSQRNetworkPlayerType playerType, bool onHost, SceNpMatching2RoomMemberId roomMemberId, int localPlayerIdx, int rudpCtx, PlayerUID *pUID)
{
m_roomMemberId = roomMemberId;
m_localPlayerIdx = localPlayerIdx;
m_rudpCtx = rudpCtx;
m_flags = 0;
m_type = playerType;
m_host = onHost;
m_manager = manager;
m_customData = 0;
if( pUID )
{
memcpy(&m_ISD.m_UID,pUID,sizeof(PlayerUID));
#ifdef __PSVITA__
if(CGameNetworkManager::usingAdhocMode() && pUID->getOnlineID()[0] == 0)
{
assert(localPlayerIdx == 0);
// player doesn't have an online UID, set it from the player name
m_ISD.m_UID.setForAdhoc();
}
#endif // __PSVITA__
}
else
{
memset(&m_ISD.m_UID,0,sizeof(PlayerUID));
}
SetNameFromUID();
InitializeCriticalSection(&m_csQueue);
#ifdef __ORBIS__
if(IsLocal())
{
SonyVoiceChat_Orbis::initLocalPlayer(m_localPlayerIdx);
}
#endif
}
SQRNetworkPlayer::~SQRNetworkPlayer()
{
#ifdef __ORBIS__
SQRNetworkManager_Orbis* pMan = (SQRNetworkManager_Orbis*)m_manager;
// pMan->removePlayerFromVoiceChat(this);
// m_roomMemberId = -1;
#endif
DeleteCriticalSection(&m_csQueue);
}
bool SQRNetworkPlayer::IsReady()
{
return ( ( m_flags & SNP_FLAG_READY_MASK ) == SNP_FLAG_READY_MASK );
}
PlayerUID SQRNetworkPlayer::GetUID()
{
return m_ISD.m_UID;
}
void SQRNetworkPlayer::SetUID(PlayerUID UID)
{
m_ISD.m_UID = UID;
SetNameFromUID();
}
bool SQRNetworkPlayer::HasConnectionAndSmallId()
{
const int reqFlags = ( SNP_FLAG_CONNECTION_COMPLETE | SNP_FLAG_SMALLID_ALLOCATED );
return (( m_flags & reqFlags) == reqFlags);
}
void SQRNetworkPlayer::ConnectionComplete()
{
m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:");
app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ConnectionComplete\n");
m_flags |= SNP_FLAG_CONNECTION_COMPLETE;
}
void SQRNetworkPlayer::SmallIdAllocated(unsigned char smallId)
{
m_ISD.m_smallId = smallId;
m_flags |= SNP_FLAG_SMALLID_ALLOCATED;
m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:");
app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID allocated\n");
// If this is a non-network sort of player then flag now as having its small id confirmed
if( ( m_type == SNP_TYPE_HOST ) ||
( m_host && ( m_type == SNP_TYPE_LOCAL ) ) ||
( !m_host && ( m_type == SNP_TYPE_REMOTE ) ) )
{
m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:");
app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID confirmed\n");
m_flags |= SNP_FLAG_SMALLID_CONFIRMED;
}
}
void SQRNetworkPlayer::InitialDataReceived(SQRNetworkPlayer::InitSendData *ISD)
{
assert(m_ISD.m_smallId == ISD->m_smallId);
memcpy(&m_ISD, ISD, sizeof(InitSendData) );
#ifdef __PSVITA__
SetNameFromUID();
#endif
m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:");
app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID confirmed\n");
m_flags |= SNP_FLAG_SMALLID_CONFIRMED;
}
bool SQRNetworkPlayer::HasSmallIdConfirmed()
{
return ( m_flags & SNP_FLAG_SMALLID_CONFIRMED );
}
// To confirm to the host that we are ready, send a single byte with our small id.
void SQRNetworkPlayer::ConfirmReady()
{
#ifdef __PS3__
int ret = cellRudpWrite( m_rudpCtx, &m_ISD, sizeof(InitSendData), CELL_RUDP_MSG_LATENCY_CRITICAL );
#else //__ORBIS__
int ret = sceRudpWrite( m_rudpCtx, &m_ISD, sizeof(InitSendData), SCE_RUDP_MSG_LATENCY_CRITICAL );
#endif
// TODO - error handling here?
assert ( ret == sizeof(InitSendData) );
// Final flag for a local player on the client, as we are now safe to send data on to the host
m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:");
app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID confirmed\n");
m_flags |= SNP_FLAG_SMALLID_CONFIRMED;
}
// Attempt to send data, of any size, from this player to that specified by pPlayerTarget. This may not be possible depending on the two players, due to
// our star shaped network connectivity. Data may be any size, and is copied so on returning from this method it does not need to be preserved.
void SQRNetworkPlayer::SendData( SQRNetworkPlayer *pPlayerTarget, const void *data, unsigned int dataSize )
{
// Our network is connected as a star. If we are the host, then we can send to any remote player. If we're a client, we can send only to the host.
// The host can also send to other local players, but this doesn't need to go through Rudp.
if( m_host )
{
if( ( m_type == SNP_TYPE_HOST ) && ( pPlayerTarget->m_type == SNP_TYPE_LOCAL ) )
{
// Special internal communication from host to local player
m_manager->LocalDataSend( this, pPlayerTarget, data, dataSize );
}
else if( ( m_type == SNP_TYPE_LOCAL ) && ( pPlayerTarget->m_type == SNP_TYPE_HOST ) )
{
// Special internal communication from local player to host
m_manager->LocalDataSend( this, pPlayerTarget, data, dataSize );
}
else if( ( m_type == SNP_TYPE_HOST ) && ( pPlayerTarget->m_type == SNP_TYPE_REMOTE ) )
{
// Rudp communication from host to remote player - handled by remote player instance
pPlayerTarget->SendInternal(data,dataSize);
}
else
{
// Can't do any other types of communications
assert(false);
}
}
else
{
if( ( m_type == SNP_TYPE_LOCAL ) && ( pPlayerTarget->m_type == SNP_TYPE_HOST ) )
{
// Rudp communication from client to host - handled by this player instace
SendInternal(data, dataSize);
}
else
{
// Can't do any other types of communications
assert(false);
}
}
}
// Internal send function - to simplify the number of mechanisms we have for sending data, this method just adds the data to be send to the player's internal queue,
// and then calls SendMoreInternal. This method can take any size of data, which it will split up into payload size chunks before sending. All input data is copied
// into internal buffers.
void SQRNetworkPlayer::SendInternal(const void *data, unsigned int dataSize)
{
EnterCriticalSection(&m_csQueue);
QueuedSendBlock sendBlock;
unsigned char *dataCurrent = (unsigned char *)data;
unsigned int dataRemaining = dataSize;
while( dataRemaining )
{
int dataSize = dataRemaining;
if( dataSize > SNP_MAX_PAYLOAD ) dataSize = SNP_MAX_PAYLOAD;
sendBlock.start = new unsigned char [dataSize];
sendBlock.end = sendBlock.start + dataSize;
sendBlock.current = sendBlock.start;
memcpy( sendBlock.start, dataCurrent, dataSize);
m_sendQueue.push(sendBlock);
dataRemaining -= dataSize;
dataCurrent += dataSize;
}
// Now try and send as much as we can
SendMoreInternal();
LeaveCriticalSection(&m_csQueue);
}
// Internal send function. This attempts to send as many elements in the queue as possible until the write function tells us that we can't send any more. This way,
// we are guaranteed that if there *is* anything more in the queue left to send, we'll get a CELL_RUDP_CONTEXT_EVENT_WRITABLE event when whatever we've managed to
// send here is complete, and can continue on.
void SQRNetworkPlayer::SendMoreInternal()
{
EnterCriticalSection(&m_csQueue);
bool keepSending;
do
{
keepSending = false;
if( m_sendQueue.size() > 0)
{
// Attempt to send the full data in the first element in our queue
unsigned char *data= m_sendQueue.front().current;
int dataSize = m_sendQueue.front().end - m_sendQueue.front().current;
#ifdef __PS3__
int ret = cellRudpWrite( m_rudpCtx, data, dataSize, 0);//CELL_RUDP_MSG_LATENCY_CRITICAL );
int wouldBlockFlag = CELL_RUDP_ERROR_WOULDBLOCK;
#else // __ORBIS__
int ret = sceRudpWrite( m_rudpCtx, data, dataSize, 0);//CELL_RUDP_MSG_LATENCY_CRITICAL );
int wouldBlockFlag = SCE_RUDP_ERROR_WOULDBLOCK;
#endif
if( ret == dataSize )
{
// Fully sent, remove from queue - will loop in the while loop to see if there's anything else in the queue we could send
delete [] m_sendQueue.front().start;
m_sendQueue.pop();
if( m_sendQueue.size() )
{
keepSending = true;
}
}
else if( ( ret >= 0 ) || ( ret == wouldBlockFlag ) )
{
// Things left to send - adjust this element in the queue
int remainingBytes;
if( ret >= 0 )
{
// Only ret bytes sent so far
remainingBytes = dataSize - ret;
assert(remainingBytes > 0 );
}
else
{
// Is CELL_RUDP_ERROR_WOULDBLOCK, nothing has yet been sent
remainingBytes = dataSize;
}
m_sendQueue.front().current = m_sendQueue.front().end - remainingBytes;
}
}
} while (keepSending);
LeaveCriticalSection(&m_csQueue);
}
void SQRNetworkPlayer::SetNameFromUID()
{
mbstowcs(m_name, m_ISD.m_UID.getOnlineID(), 16);
m_name[16] = 0;
#ifdef __PS3__ // only 1 player on vita, and they have to be online (or adhoc), and with PS4 all local players need to be signed in
// Not an online player? Add a suffix with the controller ID on
if( m_ISD.m_UID.isSignedIntoPSN() == 0)
{
int pos = wcslen(m_name);
swprintf(&m_name[pos], 5, L" (%d)", m_ISD.m_UID.getQuadrant() + 1 );
}
#endif
}
void SQRNetworkPlayer::SetName(char *name)
{
mbstowcs(m_name, name, 20);
m_name[20] = 0;
}
int SQRNetworkPlayer::GetSessionIndex()
{
return m_manager->GetSessionIndex(this);
}
bool SQRNetworkPlayer::HasVoice()
{
#ifdef __ORBIS__
return SonyVoiceChat_Orbis::hasMicConnected(this);
#elif defined __PSVITA__
return SonyVoiceChat_Vita::hasMicConnected(this);
#else
return SonyVoiceChat::hasMicConnected(&m_roomMemberId);
#endif
}
bool SQRNetworkPlayer::IsTalking()
{
#ifdef __ORBIS__
return SonyVoiceChat_Orbis::isTalking(this);
#elif defined __PSVITA__
return SonyVoiceChat_Vita::isTalking(this);
#else
return SonyVoiceChat::isTalking(&m_roomMemberId);
#endif
}
bool SQRNetworkPlayer::IsMutedByLocalUser(int userIndex)
{
#ifdef __ORBIS__
// assert(0); // this is never called, so isn't implemented in the PS4 voice stuff at the moment
return false;
#elif defined __PSVITA__
return false;// this is never called, so isn't implemented in the Vita voice stuff at the moment
#else
SQRNetworkManager_PS3* pMan = (SQRNetworkManager_PS3*)m_manager;
return SonyVoiceChat::isMutedPlayer(pMan->m_roomSyncData.players[userIndex].m_roomMemberId);
#endif
}

View File

@@ -0,0 +1,103 @@
#pragma once
#include "SQRNetworkManager.h"
#include <queue>
// This is the lowest level class for handling the concept of a player on Sony platforms. This is managed by SQRNetworkManager. The game shouldn't directly communicate
// with this class, as it is wrapped by NetworkPlayerSony which is an implementation of a platform-independent interface INetworkPlayer.
class SQRNetworkPlayer
{
#ifdef __ORBIS__
friend class SQRNetworkManager_Orbis;
friend class SonyVoiceChat_Orbis;
#elif defined __PS3__
friend class SQRNetworkManager_PS3;
#else // __PSVITA__
friend class SQRNetworkManager_Vita;
friend class SQRNetworkManager_AdHoc_Vita;
friend class SonyVoiceChat_Vita;
#endif
friend class SQRNetworkManager;
friend class NetworkPlayerSony;
friend class CPlatformNetworkManagerSony;
int GetSmallId();
wchar_t *GetName();
bool IsRemote();
bool IsHost();
bool IsLocal();
int GetLocalPlayerIndex();
bool IsSameSystem(SQRNetworkPlayer *other);
uintptr_t GetCustomDataValue();
void SetCustomDataValue(uintptr_t data);
bool HasVoice();
bool IsTalking();
bool IsMutedByLocalUser(int userIndex);
static const int SNP_FLAG_CONNECTION_COMPLETE = 1; // This player has a fully connected Rudp or other local link established (to a remote player if this is on the host, to the host if this is a client) - or isn't expected to have one
static const int SNP_FLAG_SMALLID_ALLOCATED = 2; // This player has a small id allocated
static const int SNP_FLAG_SMALLID_CONFIRMED = 4; // This player's small id has been confirmed as received by the client (only relevant for players using network communications, others set at the same time as allocating)
static const int SNP_FLAG_READY_MASK = 7; // Mask indicated all bits which must be set in the flags for this player to be considered "ready"
static const int SNP_MAX_PAYLOAD = 1346; // This is the default RUDP payload size - if we want to change this we'll need to use cellRudpSetOption to set something else & adjust segment size
typedef enum
{
SNP_TYPE_HOST, // This player represents the host
SNP_TYPE_LOCAL, // On host - this player is a local player that needs communicated with specially not using rudp. On clients - this is a local player, where m_rudpCtx is the context used to communicate from this player to/from the host
SNP_TYPE_REMOTE, // On host - this player's m_rupdCtx can be used to communicate from between the host and this player. On clients - this is a remote player that cannot be communicated with
} eSQRNetworkPlayerType;
class QueuedSendBlock
{
public:
unsigned char *start;
unsigned char *end;
unsigned char *current;
};
class InitSendData
{
public:
unsigned char m_smallId; // Id to uniquely and permanently identify this player between machines - assigned by the server
PlayerUID m_UID;
};
SQRNetworkPlayer(SQRNetworkManager *manager, eSQRNetworkPlayerType playerType, bool onHost, SceNpMatching2RoomMemberId roomMemberId, int localPlayerIdx, int rudpCtx, PlayerUID *pUID);
~SQRNetworkPlayer();
PlayerUID GetUID();
void SetUID(PlayerUID UID);
bool HasConnectionAndSmallId();
bool IsReady();
void ConnectionComplete();
void SmallIdAllocated(unsigned char smallId);
void InitialDataReceived(InitSendData *ISD); // Only for remote players as viewed from the host, this is set when the host has received confirmation that the client has received the small id for this player, ie it is now safe to send data to
bool HasSmallIdConfirmed();
void SendData( SQRNetworkPlayer *pPlayerTarget, const void *data, unsigned int dataSize );
void ConfirmReady();
void SendInternal(const void *data, unsigned int dataSize);
void SendMoreInternal();
#ifdef __PSVITA__
void SendInternal_VitaAdhoc(const void *data, unsigned int dataSize, EAdhocDataTag tag = e_dataTag_Normal);
void SendMoreInternal_VitaAdhoc();
#endif
void SetNameFromUID();
void SetName(char *name);
int GetSessionIndex();
eSQRNetworkPlayerType m_type; // The player type
bool m_host; // Whether this actual player class is stored on a host (not whether it represents the host, or a player on the host machine)
int m_flags; // Flags reflecting current state of this player
int m_rudpCtx; // Rudp context that can be used to communicate between this player & the host (see comments for eSQRNetworkPlayerType above)
int m_localPlayerIdx; // Index of this player on the machine to which it belongs
SceNpMatching2RoomMemberId m_roomMemberId; // The room member id, effectively a per machine id
InitSendData m_ISD; // Player UID & ID that get sent together to the host when connection is established
SQRNetworkManager *m_manager; // Pointer back to the manager that is managing this player
wchar_t m_name[21];
uintptr_t m_customData;
CRITICAL_SECTION m_csQueue;
std::queue<QueuedSendBlock> m_sendQueue;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __PS3__
#include <np.h>
#include <np/drm.h>
#include <np/commerce2.h>
#elif defined __PSVITA__
#include <np.h>
#include <np_toolkit.h>
#else // __ORBIS__
#define SCE_NP_COMMERCE2_CATEGORY_ID_LEN SCE_TOOLKIT_NP_COMMERCE_CATEGORY_ID_LEN ///< The size of the category ID.
#define SCE_NP_COMMERCE2_PRODUCT_ID_LEN SCE_TOOLKIT_NP_COMMERCE_PRODUCT_ID_LEN ///< The size of the product ID.
#define SCE_NP_COMMERCE2_CATEGORY_NAME_LEN SCE_TOOLKIT_NP_COMMERCE_CATEGORY_NAME_LEN ///< The size of the category name.
#define SCE_NP_COMMERCE2_CATEGORY_DESCRIPTION_LEN SCE_TOOLKIT_NP_COMMERCE_CATEGORY_DESCRIPTION_LEN ///< The size of the category description.
#define SCE_NP_COMMERCE2_URL_LEN SCE_TOOLKIT_NP_COMMERCE_URL_LEN ///< The size of the URL.
#define SCE_NP_COMMERCE2_PRODUCT_NAME_LEN SCE_TOOLKIT_NP_COMMERCE_PRODUCT_NAME_LEN ///< The size of the product name.
#define SCE_NP_COMMERCE2_PRODUCT_SHORT_DESCRIPTION_LEN SCE_TOOLKIT_NP_COMMERCE_PRODUCT_SHORT_DESCRIPTION_LEN ///< The size of the product short description.
#define SCE_NP_COMMERCE2_SP_NAME_LEN SCE_TOOLKIT_NP_COMMERCE_SP_NAME_LEN ///< The size of the licensee (publisher) name.
#define SCE_NP_COMMERCE2_CURRENCY_CODE_LEN SCE_TOOLKIT_NP_COMMERCE_CURRENCY_CODE_LEN ///< The size of currency code.
#define SCE_NP_COMMERCE2_CURRENCY_CODE_LEN SCE_TOOLKIT_NP_COMMERCE_CURRENCY_CODE_LEN
#define SCE_NP_COMMERCE2_CURRENCY_SYMBOL_LEN SCE_TOOLKIT_NP_COMMERCE_CURRENCY_SYMBOL_LEN ///< The size of currency symbol.
#define SCE_NP_COMMERCE2_THOUSAND_SEPARATOR_LEN SCE_TOOLKIT_NP_COMMERCE_THOUSAND_SEPARATOR_LEN ///< The size of the character separating every 3 digits of the price.
#define SCE_NP_COMMERCE2_DECIMAL_LETTER_LEN SCE_TOOLKIT_NP_COMMERCE_DECIMAL_LETTER_LEN ///< The size of the character indicating the decimal point in the price.
#define SCE_NP_COMMERCE2_SKU_ID_LEN SCE_TOOLKIT_NP_COMMERCE_SKU_ID_LEN ///< The size of the SKU ID.
#define SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN SCE_TOOLKIT_NP_COMMERCE_PRODUCT_LONG_DESCRIPTION_LEN ///< The size of the product long description.
#define SCE_NP_COMMERCE2_PRODUCT_LEGAL_DESCRIPTION_LEN SCE_TOOLKIT_NP_COMMERCE_PRODUCT_LEGAL_DESCRIPTION_LEN ///< The size of the product legal description.
#define SCE_NP_COMMERCE2_RATING_SYSTEM_ID_LEN SCE_TOOLKIT_NP_COMMERCE_RATING_SYSTEM_ID_LEN ///< The size of the rating system ID.
#define SCE_NP_ENTITLEMENT_ID_SIZE SCE_TOOLKIT_NP_COMMERCE_ENTITLEMENT_ID_LEN ///< The size of entitlement ID.
#endif
#ifndef __PSVITA__
#define SCE_TOOLKIT_NP_SKU_PRICE_LEN (SCE_NP_COMMERCE2_CURRENCY_CODE_LEN \
+ SCE_NP_COMMERCE2_CURRENCY_SYMBOL_LEN \
+ SCE_NP_COMMERCE2_THOUSAND_SEPARATOR_LEN \
+ SCE_NP_COMMERCE2_DECIMAL_LETTER_LEN) ///< The maximum length of a price in characters.
#endif
class SonyCommerce
{
public:
typedef void (*CallbackFunc)(LPVOID lpParam, int error_code);
/// @brief
/// Contains information about a subcategory on the PlayStation(R)Store.
///
/// Contains information about a subcategory on the PlayStation(R)Store.
typedef struct CategoryInfoSub
{
char categoryId[SCE_NP_COMMERCE2_CATEGORY_ID_LEN]; ///< The ID of the subcategory.
char categoryName[SCE_NP_COMMERCE2_CATEGORY_NAME_LEN]; ///< The name of the subcategory.
char categoryDescription[SCE_NP_COMMERCE2_CATEGORY_DESCRIPTION_LEN]; ///< The detailed description of the subcategory.
char imageUrl[SCE_NP_COMMERCE2_URL_LEN]; ///< The image URL of the subcategory.
}
CategoryInfoSub;
/// @brief
/// Current category information
///
/// This structure contains information about a category on the PlayStation(R)Store
typedef struct CategoryInfo
{
CategoryInfoSub current; ///< The currently selected subcategory.
std::list<CategoryInfoSub> subCategories; ///< Information about the subcategories in this category.
uint32_t countOfProducts; ///< The number of products in the category.
uint32_t countOfSubCategories; ///< The number of subcategories.
}
CategoryInfo;
/// Contains information about a product in the PlayStation(R)Store.
typedef struct ProductInfo
{
uint32_t purchasabilityFlag; ///< A flag that indicates whether the product can be purchased (<c>SCE_NP_COMMERCE2_SKU_PURCHASABILITY_FLAG_XXX</c>).
uint32_t annotation; // SCE_NP_COMMERCE2_SKU_ANN_PURCHASED_CANNOT_PURCHASE_AGAIN or SCE_NP_COMMERCE2_SKU_ANN_PURCHASED_CAN_PURCHASE_AGAIN
uint32_t ui32Price;
char productId[SCE_NP_COMMERCE2_PRODUCT_ID_LEN]; ///< The product ID.
char productName[SCE_NP_COMMERCE2_PRODUCT_NAME_LEN]; ///< The name of the product.
char shortDescription[SCE_NP_COMMERCE2_PRODUCT_SHORT_DESCRIPTION_LEN]; ///< A short description of the product.
char longDescription[SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN]; ///< A long description of the product.
char skuId[SCE_NP_COMMERCE2_SKU_ID_LEN]; ///< The SKU ID
char spName[SCE_NP_COMMERCE2_SP_NAME_LEN]; ///< The service provider name.
char imageUrl[SCE_NP_COMMERCE2_URL_LEN]; ///< The product image URL.
char price[SCE_TOOLKIT_NP_SKU_PRICE_LEN]; ///< The price of the product. This is formatted to include the currency code.
char padding[6]; ///< Padding.
#ifdef __PS3__
CellRtcTick releaseDate; ///< The product release date.
#else
SceRtcTick releaseDate;
#endif
}
ProductInfo;
/// @brief
/// Contains detailed information about a product on the PlayStation(R)Store.
///
/// Contains detailed information about a product on the PlayStation(R)Store.
typedef struct ProductInfoDetailed
{
uint32_t purchasabilityFlag; ///< A flag that indicates whether the product can be purchased (<c>SCE_NP_COMMERCE2_SKU_PURCHASABILITY_FLAG_XXX</c>).
uint32_t ui32Price;
char skuId[SCE_NP_COMMERCE2_SKU_ID_LEN]; ///< The SKU ID
char productId[SCE_NP_COMMERCE2_PRODUCT_ID_LEN]; ///< The product ID.
char productName[SCE_NP_COMMERCE2_PRODUCT_NAME_LEN]; ///< The name of the product.
char shortDescription[SCE_NP_COMMERCE2_PRODUCT_SHORT_DESCRIPTION_LEN]; ///< A short description of the product.
char longDescription[SCE_NP_COMMERCE2_PRODUCT_LONG_DESCRIPTION_LEN]; ///< A long description of the product.
char legalDescription[SCE_NP_COMMERCE2_PRODUCT_LEGAL_DESCRIPTION_LEN]; ///< The legal description for the product.
char spName[SCE_NP_COMMERCE2_SP_NAME_LEN]; ///< The service provider name.
char imageUrl[SCE_NP_COMMERCE2_URL_LEN]; ///< The product image URL.
char price[SCE_TOOLKIT_NP_SKU_PRICE_LEN]; ///< The price of the product. This is formatted to include the currency code.
char ratingSystemId[SCE_NP_COMMERCE2_RATING_SYSTEM_ID_LEN]; ///< The ID of the rating system (for example: PEGI, ESRB).
char ratingImageUrl[SCE_NP_COMMERCE2_URL_LEN]; ///< The URL of the rating icon.
char padding[2]; ///< Padding.
#ifdef __PS3__
std::list<SceNpCommerce2ContentRatingDescriptor> ratingDescriptors; ///< The list of rating descriptors.
CellRtcTick releaseDate; ///< The product release date.
#else
SceRtcTick releaseDate; ///< The product release date.
#endif
}
ProductInfoDetailed;
/// @brief
/// Checkout parameters
///
/// This structure contains list of SKUs to checkout to and a memory container
typedef struct CheckoutInputParams
{
std::list<const char *> skuIds; ///< List of SKU IDs
#ifdef __PS3__
sys_memory_container_t *memContainer; ///< Memory container for checkout overlay
#endif
}
CheckoutInputParams;
/// @brief
/// Contains download list parameters.
///
/// Contains download list parameters.
typedef struct DownloadListInputParams
{
std::list<const char *> skuIds; ///< The list of SKU IDs
#ifdef __PS3__
sys_memory_container_t *memContainer; ///< A memory container for checkout overlay.
#endif
const char* categoryID;
}
DownloadListInputParams;
public:
virtual void CreateSession(CallbackFunc cb, LPVOID lpParam) = 0;
virtual void CloseSession() = 0;
virtual void GetCategoryInfo(CallbackFunc cb, LPVOID lpParam, CategoryInfo *info, const char *categoryId) = 0;
virtual void GetProductList(CallbackFunc cb, LPVOID lpParam, std::vector<ProductInfo>* productList, const char *categoryId) = 0;
virtual void GetDetailedProductInfo(CallbackFunc cb, LPVOID lpParam, ProductInfoDetailed* productInfoDetailed, const char *productId, const char *categoryId) = 0;
virtual void AddDetailedProductInfo( CallbackFunc cb, LPVOID lpParam, ProductInfo* productInfo, const char *productId, const char *categoryId ) = 0;
virtual void Checkout(CallbackFunc cb, LPVOID lpParam, const char* skuID) = 0;
virtual void DownloadAlreadyPurchased(CallbackFunc cb, LPVOID lpParam, const char* skuID) = 0;
#if defined(__ORBIS__) || defined( __PSVITA__)
virtual void Checkout_Game(CallbackFunc cb, LPVOID lpParam, const char* skuID) = 0;
virtual void DownloadAlreadyPurchased_Game(CallbackFunc cb, LPVOID lpParam, const char* skuID) = 0;
#endif
virtual void UpgradeTrial(CallbackFunc cb, LPVOID lpParam) = 0;
virtual void CheckForTrialUpgradeKey() = 0;
virtual bool LicenseChecked() = 0;
};

View File

@@ -0,0 +1,34 @@
#include "stdafx.h"
#include "SonyHttp.h"
#ifdef __PS3__
#include "PS3\Network\SonyHttp_PS3.h"
SonyHttp_PS3 g_SonyHttp;
#elif defined __ORBIS__
#include "Orbis\Network\SonyHttp_Orbis.h"
SonyHttp_Orbis g_SonyHttp;
#elif defined __PSVITA__
#include "PSVita\Network\SonyHttp_Vita.h"
SonyHttp_Vita g_SonyHttp;
#endif
bool SonyHttp::init()
{
return g_SonyHttp.init();
}
void SonyHttp::shutdown()
{
g_SonyHttp.shutdown();
}
bool SonyHttp::getDataFromURL(const char* szURL, void** ppOutData, int* pDataSize)
{
return g_SonyHttp.getDataFromURL(szURL, ppOutData, pDataSize);
}

View File

@@ -0,0 +1,11 @@
#pragma once
class SonyHttp
{
public:
static bool init();
static void shutdown();
static bool getDataFromURL(const char* szURL, void** ppOutData, int* pDataSize);
};

View File

@@ -0,0 +1,340 @@
#include "stdafx.h"
#include "SonyRemoteStorage.h"
static const char sc_remoteSaveFilename[] = "/minecraft_save/gamedata.rs";
#ifdef __PSVITA__
static const char sc_localSaveFilename[] = "CloudSave_Vita.bin";
static const char sc_localSaveFullPath[] = "savedata0:CloudSave_Vita.bin";
#elif defined __PS3__
static const char sc_localSaveFilename[] = "CloudSave_PS3.bin";
static const char sc_localSaveFullPath[] = "NPEB01899--140720203552";
#else
static const char sc_localSaveFilename[] = "CloudSave_Orbis.bin";
static const char sc_localSaveFullPath[] = "/app0/CloudSave_Orbis.bin";
#endif
static SceRemoteStorageStatus statParams;
// void remoteStorageGetCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code)
// {
// app.DebugPrintf("remoteStorageGetCallback err : 0x%08x\n");
// }
//
// void remoteStorageCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code)
// {
// app.DebugPrintf("remoteStorageCallback err : 0x%08x\n");
//
// app.getRemoteStorage()->getRemoteFileInfo(&statParams, remoteStorageGetInfoCallback, NULL);
// }
void getSaveInfoReturnCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code)
{
SonyRemoteStorage* pRemoteStorage = (SonyRemoteStorage*)lpParam;
app.DebugPrintf("remoteStorageGetInfoCallback err : 0x%08x\n", error_code);
if(error_code == 0)
{
for(int i=0;i<statParams.numFiles;i++)
{
if(strcmp(statParams.data[i].fileName, sc_remoteSaveFilename) == 0)
{
// found the file we need in the cloud
pRemoteStorage->m_getInfoStatus = SonyRemoteStorage::e_infoFound;
pRemoteStorage->m_remoteFileInfo = &statParams.data[i];
}
}
}
if(pRemoteStorage->m_getInfoStatus != SonyRemoteStorage::e_infoFound)
pRemoteStorage->m_getInfoStatus = SonyRemoteStorage::e_noInfoFound;
}
static void getSaveInfoInitCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code)
{
SonyRemoteStorage* pRemoteStorage = (SonyRemoteStorage*)lpParam;
if(error_code != 0)
{
app.DebugPrintf("getSaveInfoInitCallback err : 0x%08x\n", error_code);
pRemoteStorage->m_getInfoStatus = SonyRemoteStorage::e_noInfoFound;
}
else
{
app.DebugPrintf("getSaveInfoInitCallback calling getRemoteFileInfo\n");
app.getRemoteStorage()->getRemoteFileInfo(&statParams, getSaveInfoReturnCallback, pRemoteStorage);
}
}
void SonyRemoteStorage::getSaveInfo()
{
if(m_getInfoStatus == e_gettingInfo)
{
app.DebugPrintf("SonyRemoteStorage::getSaveInfo already running!!!\n");
return;
}
m_getInfoStatus = e_gettingInfo;
if(!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()))
{
m_getInfoStatus = e_noInfoFound;
return;
}
app.DebugPrintf("SonyRemoteStorage::getSaveInfo calling init\n");
bool bOK = init(getSaveInfoInitCallback, this);
if(!bOK)
m_getInfoStatus = e_noInfoFound;
}
bool SonyRemoteStorage::getSaveData( const char* localDirname, CallbackFunc cb, LPVOID lpParam )
{
m_startTime = System::currentTimeMillis();
m_dataProgress = 0;
return getData(sc_remoteSaveFilename, localDirname, cb, lpParam);
}
static void setSaveDataInitCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int error_code)
{
SonyRemoteStorage* pRemoteStorage = (SonyRemoteStorage*)lpParam;
if(error_code != 0)
{
app.DebugPrintf("setSaveDataInitCallback err : 0x%08x\n", error_code);
pRemoteStorage->m_setDataStatus = SonyRemoteStorage::e_settingDataFailed;
if(pRemoteStorage->m_initCallbackFunc)
pRemoteStorage->m_initCallbackFunc(pRemoteStorage->m_initCallbackParam, s, error_code);
}
else
{
app.getRemoteStorage()->setData(pRemoteStorage->m_setSaveDataInfo, pRemoteStorage->m_initCallbackFunc, pRemoteStorage->m_initCallbackParam);
}
}
bool SonyRemoteStorage::setSaveData(PSAVE_INFO info, CallbackFunc cb, void* lpParam)
{
m_setSaveDataInfo = info;
m_setDataStatus = e_settingData;
m_initCallbackFunc = cb;
m_initCallbackParam = lpParam;
m_dataProgress = 0;
bool bOK = init(setSaveDataInitCallback, this);
if(!bOK)
m_setDataStatus = e_settingDataFailed;
return bOK;
}
const char* SonyRemoteStorage::getLocalFilename()
{
return sc_localSaveFullPath;
}
const char* SonyRemoteStorage::getSaveNameUTF8()
{
if(m_getInfoStatus != e_infoFound)
return NULL;
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
return pDescData->m_saveNameUTF8;
}
ESavePlatform SonyRemoteStorage::getSavePlatform()
{
if(m_getInfoStatus != e_infoFound)
return SAVE_FILE_PLATFORM_NONE;
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
return (ESavePlatform)MAKE_FOURCC(pDescData->m_platform[0], pDescData->m_platform[1], pDescData->m_platform[2], pDescData->m_platform[3]);
}
__int64 SonyRemoteStorage::getSaveSeed()
{
if(m_getInfoStatus != e_infoFound)
return 0;
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
char seedString[17];
ZeroMemory(seedString,17);
memcpy(seedString, pDescData->m_seed,16);
__uint64 seed = 0;
std::stringstream ss;
ss << seedString;
ss >> std::hex >> seed;
return seed;
}
unsigned int SonyRemoteStorage::getSaveHostOptions()
{
if(m_getInfoStatus != e_infoFound)
return 0;
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
char optionsString[9];
ZeroMemory(optionsString,9);
memcpy(optionsString, pDescData->m_hostOptions,8);
unsigned int uiHostOptions = 0;
std::stringstream ss;
ss << optionsString;
ss >> std::hex >> uiHostOptions;
return uiHostOptions;
}
unsigned int SonyRemoteStorage::getSaveTexturePack()
{
if(m_getInfoStatus != e_infoFound)
return 0;
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
char textureString[9];
ZeroMemory(textureString,9);
memcpy(textureString, pDescData->m_texturePack,8);
unsigned int uiTexturePack = 0;
std::stringstream ss;
ss << textureString;
ss >> std::hex >> uiTexturePack;
return uiTexturePack;
}
const char* SonyRemoteStorage::getRemoteSaveFilename()
{
return sc_remoteSaveFilename;
}
int SonyRemoteStorage::getSaveFilesize()
{
if(m_getInfoStatus == e_infoFound)
{
return m_remoteFileInfo->fileSize;
}
return 0;
}
bool SonyRemoteStorage::setData( PSAVE_INFO info, CallbackFunc cb, LPVOID lpParam )
{
m_setDataSaveInfo = info;
m_callbackFunc = cb;
m_callbackParam = lpParam;
m_status = e_setDataInProgress;
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(info,&LoadSaveDataThumbnailReturned,this);
return true;
}
int SonyRemoteStorage::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes)
{
SonyRemoteStorage *pClass= (SonyRemoteStorage *)lpParam;
if(pClass->m_bAborting)
{
pClass->runCallback();
return 0;
}
app.DebugPrintf("Received data for a thumbnail\n");
if(pbThumbnail && dwThumbnailBytes)
{
pClass->m_thumbnailData = pbThumbnail;
pClass->m_thumbnailDataSize = dwThumbnailBytes;
}
else
{
app.DebugPrintf("Thumbnail data is NULL, or has size 0\n");
pClass->m_thumbnailData = NULL;
pClass->m_thumbnailDataSize = 0;
}
if(pClass->m_SetDataThread != NULL)
delete pClass->m_SetDataThread;
pClass->m_SetDataThread = new C4JThread(setDataThread, pClass, "setDataThread");
pClass->m_SetDataThread->Run();
return 0;
}
int SonyRemoteStorage::setDataThread(void* lpParam)
{
SonyRemoteStorage* pClass = (SonyRemoteStorage*)lpParam;
pClass->m_startTime = System::currentTimeMillis();
pClass->setDataInternal();
return 0;
}
bool SonyRemoteStorage::saveIsAvailable()
{
if(m_getInfoStatus != e_infoFound)
return false;
#ifdef __PS3__
return (getSavePlatform() == SAVE_FILE_PLATFORM_PSVITA);
#elif defined __PSVITA__
return (getSavePlatform() == SAVE_FILE_PLATFORM_PS3);
#else // __ORBIS__
return true;
#endif
}
int SonyRemoteStorage::getDataProgress()
{
__int64 time = System::currentTimeMillis();
int elapsedSecs = (time - m_startTime) / 1000;
int progVal = m_dataProgress + (elapsedSecs/3);
if(progVal > 95)
{
return m_dataProgress;
}
return progVal;
}
bool SonyRemoteStorage::shutdown()
{
if(m_bInitialised)
{
int ret = sceRemoteStorageTerm();
if(ret >= 0)
{
app.DebugPrintf("Term request done \n");
m_bInitialised = false;
free(m_memPoolBuffer);
m_memPoolBuffer = NULL;
return true;
}
else
{
app.DebugPrintf("Error in Term request: 0x%x \n", ret);
return false;
}
}
return true;
}
void SonyRemoteStorage::waitForStorageManagerIdle()
{
C4JStorage::ESaveGameState storageState = StorageManager.GetSaveState();
while(storageState != C4JStorage::ESaveGame_Idle)
{
Sleep(10);
// app.DebugPrintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>> storageState = %d\n", storageState);
storageState = StorageManager.GetSaveState();
}
}

View File

@@ -0,0 +1,120 @@
#pragma once
#include "..\..\Common\Network\Sony\sceRemoteStorage\header\sceRemoteStorage.h"
class SonyRemoteStorage
{
public:
enum Status
{
e_idle,
e_accountLinked,
e_error,
e_signInRequired,
e_compressInProgress,
e_setDataInProgress,
e_setDataSucceeded,
e_getDataInProgress,
e_getDataSucceeded,
e_getStatusInProgress,
e_getStatusSucceeded
};
typedef void (*CallbackFunc)(LPVOID lpParam, Status s, int error_code);
enum GetInfoStatus
{
e_gettingInfo,
e_infoFound,
e_noInfoFound
};
GetInfoStatus m_getInfoStatus;
enum SetDataStatus
{
e_settingData,
e_settingDataFailed,
e_settingDataSucceeded
};
SetDataStatus m_setDataStatus;
PSAVE_INFO m_setSaveDataInfo;
SceRemoteStorageData* m_remoteFileInfo;
class DescriptionData
{
// this stuff is read from a JSON query, so it all has to be text based, max 256 bytes
public:
char m_platform[4];
char m_seed[16]; // 8 bytes as hex
char m_hostOptions[8]; // 4 bytes as hex
char m_texturePack[8]; // 4 bytes as hex
char m_saveNameUTF8[128];
};
CallbackFunc m_callbackFunc;
void* m_callbackParam;
CallbackFunc m_initCallbackFunc;
void* m_initCallbackParam;
void getSaveInfo();
bool waitingForSaveInfo() { return (m_getInfoStatus == e_gettingInfo); }
bool saveIsAvailable();
int getSaveFilesize();
bool getSaveData(const char* localDirname, CallbackFunc cb, LPVOID lpParam);
bool setSaveData(PSAVE_INFO info, CallbackFunc cb, void* lpParam);
bool waitingForSetData() { return (m_setDataStatus == e_settingData); }
const char* getLocalFilename();
const char* getSaveNameUTF8();
ESavePlatform getSavePlatform();
__int64 getSaveSeed();
unsigned int getSaveHostOptions();
unsigned int getSaveTexturePack();
void SetServiceID(char *pchServiceID) { m_pchServiceID=pchServiceID; }
virtual bool init(CallbackFunc cb, LPVOID lpParam) = 0;
virtual bool getRemoteFileInfo(SceRemoteStorageStatus* pInfo, CallbackFunc cb, LPVOID lpParam) = 0;
virtual bool getData(const char* remotePath, const char* localPath, CallbackFunc cb, LPVOID lpParam) = 0;
virtual void abort() = 0;
virtual bool shutdown();
virtual bool setDataInternal() = 0;
virtual void runCallback() = 0;
Status getStatus() { return m_status; }
int getDataProgress();
void waitForStorageManagerIdle();
bool setData( PSAVE_INFO info, CallbackFunc cb, LPVOID lpParam );
static int LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes);
static int setDataThread(void* lpParam);
SonyRemoteStorage() : m_memPoolBuffer(NULL), m_bInitialised(false),m_getInfoStatus(e_noInfoFound) {}
protected:
const char* getRemoteSaveFilename();
bool m_bInitialised;
void* m_memPoolBuffer;
Status m_status;
int m_dataProgress;
char *m_pchServiceID;
PBYTE m_thumbnailData;
unsigned int m_thumbnailDataSize;
C4JThread* m_SetDataThread;
PSAVE_INFO m_setDataSaveInfo;
__int64 m_startTime;
bool m_bAborting;
bool m_bTransferStarted;
};

View File

@@ -0,0 +1,137 @@
#ifndef SCE_REMOTE_STORAGE_H
#define SCE_REMOTE_STORAGE_H
#include "sceRemoteStorageDefines.h"
/// @brief
/// Initialises the RemoteStorage library.
///
/// Initialises the RemoteStorage library, creates a session on the server and starts the Thread to process requests.
/// This method must be executed to start the RemoteStorage library or none of its functionality will be available.
/// This method will block while it initializes its thread and will return an error if it is
/// unable to do so. The session will be created on the thread once this is created and it won't be a blocking operation.
///
/// It is important to note that HTTP, SSL and NET libraries are not being initialised by the library and should be initialised outside of it.
///
/// @param params The structure of type <>SceRemoteStorageInitParams</c> that contains necessary information to start the library.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successfully registered on the thread.
/// @retval SCE_REMOTE_STORAGE_ERROR_INVALID_ARGUMENT At least one of the arguments passed in the input structure is not valid.
/// @retval SCE_REMOTE_STORAGE_ERROR_FAILED_TO_ALLOCATE There is no enough memory on the library to perform an allocation.
/// @retval USER_ACCOUNT_LINKED This event will be sent to the event callback when the session is created and linked to PSN on the server
/// @retval PSN_SIGN_IN_REQUIRED This event will be sent to the event callback when the session is created but not linked to PSN on the server.
/// This will only happen on the PC version and requires to call <c>sceRemoteStorageOpenWebBrowser()</c> function.
/// @retval ERROR_OCCURRED This event will be sent to the event callback when an error has occurred in the thread.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageInit(const SceRemoteStorageInitParams & params);
/// @brief
/// Terminates the RemoteStorage library.
///
/// Terminates the RemoteStorage library and deletes the thread that process requests.
/// This method must be executed to terminate the RemoteStorage library to prevent leaks in memory and resources.
/// This method will abort any other pending requests and terminate the library. It won't wait for requests to finish.
/// This method is synchronous and does not make use of the callback to inform the user of success termination. It is executed on the calling thread.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successful.
/// @retval SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED The RemoteStorage library was not initialised.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageTerm();
/// @brief
/// Aborts a request sent to the RemoteStorage library.
///
/// Aborts a request being processed or pending to be processed by the RemoteStorage library.
/// This method is synchronous and does not make use of the callback to inform the user of success termination. It is executed on the calling thread.
///
/// @param param A structure containing the request Id to be aborted.
/// This request Id is provided by other functions (get/setData, getStatus and OpenWebBrowser) so they can be referenced.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successful.
/// @retval SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED The RemoteStorage library was not initialised.
/// @retval SCE_REMOTE_STORAGE_ERROR_REQ_ID_NOT_FOUND The request Id sent is not found.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageAbort(const SceRemoteStorageAbortReqParams & params);
/// @brief
/// Opens the default web browser to sign in to PSN on PC.
///
/// Opens the default web browser to sign in to PSN on PC. This function does not have any functionality on other platforms.
/// This method does make use of the callback to inform the user of success termination. This function has priority over other functions on the thread (as getData(), getStatus()
/// and setData()) and it will be executed as soon as the thread finishes processing a pending request.
///
/// @param param The structure containing extra parameters to be passed in. This structure does only exist for future expansions.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successfully registered on the thread.
/// @retval SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED The RemoteStorage library was not initialised.
/// @retval SCE_REMOTE_STORAGE_ERROR_FAILED_TO_ALLOCATE There is no enough memory on the library to perform an allocation.
/// @retval ERROR_OCCURRED This event will be sent to the event callback when an error has occurred in the thread.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageOpenWebBrowser(const SceRemoteStorageWebBrowserReqParams & params);
/// @brief
/// Gives details for all files of a user.
///
/// Gives details for all files of a user. It provides generic information (remaining bandwidth per day, HDD space per user, number of files) as well as
/// specific file information (number of bytes, file name, file description, MD5 checksum, timestamp and file visibility). File data is not provided.
/// This method does make use of the callback to inform the user of success termination. The SceRemoteStorageStatus pointer must be pointer a to a valid
/// location in memory until the callback is called as the output information will be stored in such location.
///
/// @param params The structure containing extra parameters to be passed in. This structure does only exist for future expansions.
/// @param status The structure where the output information will be stored. The memory location being pointed must be valid until the callback gets called.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successfully registered on the thread.
/// @retval SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED The RemoteStorage library was not initialised.
/// @retval SCE_REMOTE_STORAGE_ERROR_FAILED_TO_ALLOCATE There is no enough memory on the library to perform an allocation.
/// @retval ERROR_OCCURRED This event will be sent to the event callback when an error has occurred in the thread.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageGetStatus(const SceRemoteStorageStatusReqParams & params, SceRemoteStorageStatus * status);
/// @brief
/// Gets section of data from a file specified.
///
/// Gets section of data from a file specified. The amount of data requested can be of any size. To request this information the name of file, the number of bytes and
/// the byte to start reading along with a buffer to store such data must be provided.
/// Metadata information of the file, as description or visibility, will be provided only in the case the first amount of bytes for the file are requested (offset = 0).
/// This method does make use of the callback to inform the user of success termination. The SceRemoteStorageData pointer must be a pointer to a valid
/// location in memory until the callback is called as the output information will be stored in such location.
///
/// @param params The structure containing the file name to read, the start byte to start reading and the amount of bytes to read.
/// @param status The structure where the output information will be stored. The memory location being pointed must be valid until the callback gets called.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successfully registered on the thread.
/// @retval SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED The RemoteStorage library was not initialised.
/// @retval SCE_REMOTE_STORAGE_ERROR_FAILED_TO_ALLOCATE There is no enough memory on the library to perform an allocation.
/// @retval ERROR_OCCURRED This event will be sent to the event callback when an error has occurred in the thread.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageGetData(const SceRemoteStorageGetDataReqParams & params, SceRemoteStorageData * data);
/// @brief
/// Sets chunk of data to a file specified.
///
/// Sets chunk of data to a file specified. The amount of data sent must be of, at least, 5 Megabytes per chunk excepts
/// in the case of the last chunk of the file (or the only one if that is the case) as it can be smaller.
/// The information provided regarding the chunk as the chunk number, total number of chunks, data buffer and its size should be provided in every call.
/// The information provided regarding the file as its name, description and visibility should be provided in the last chunk only (this is, when
/// chunk number = number of chunks).
/// This method does make use of the callback to inform the user of success termination. The data attribute of the SceRemoteStorageSetDataReqParams pointer
/// must be a pointer to a valid location in memory until the callback is called as the buffer won't be copied internally.
///
/// @param data The structure containing the chunk information.
///
/// @retval SCE_REMOTE_STORAGE_SUCCESS The operation was successfully registered on the thread.
/// @retval SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED The RemoteStorage library was not initialised.
/// @retval SCE_REMOTE_STORAGE_ERROR_FAILED_TO_ALLOCATE There is no enough memory on the library to perform an allocation.
/// @retval ERROR_OCCURRED This event will be sent to the event callback when an error has occurred in the thread.
///
/// @note System errors may be returned. Design your code so it does expect other errors.
int32_t sceRemoteStorageSetData(const SceRemoteStorageSetDataReqParams & data);
#endif

View File

@@ -0,0 +1,167 @@
#ifndef SCE_REMOTE_STORAGE_DEFINES_H
#define SCE_REMOTE_STORAGE_DEFINES_H
#ifdef __psp2__
#include <stddef.h>
#include <apputil.h>
#elif __ORBIS__
#include <stddef.h>
#define SceAppUtilSaveDataDataSlot int
#elif __PS3__
#define SceAppUtilSaveDataDataSlot int
#endif
#include <stdint.h>
// Macros
#define SCE_REMOTE_STORAGE_MAX_FILES 16
#define SCE_REMOTE_STORAGE_DATA_NAME_MAX_LEN 64
#define SCE_REMOTE_STORAGE_CLIENT_ID_MAX_LEN 64
#define SCE_REMOTE_STORAGE_PLATFORM_NAME_MAX_LEN 16
#define SCE_REMOTE_STORAGE_MD5_STRING_LENGTH 33
#define SCE_REMOTE_STORAGE_RFC2822_LENGTH 32
#define SCE_REMOTE_STORAGE_DATA_DESCRIPTION_MAX_LEN 256
#define SCE_REMOTE_STORAGE_DATA_LOCATION_MAX_LEN 256
#define SCE_REMOTE_STORAGE_PS3_SAVEDATA_SECUREFILEID_SIZE 16
#define SCE_REMOTE_STORAGE_PS3_SAVEDATA_FILENAME_SIZE 13
#define SCE_REMOTE_STORAGE_AUTH_CODE_MAX_LEN 128
// Return values
#define SCE_REMOTE_STORAGE_SUCCESS 0
// Error codes
#define SCE_REMOTE_STORAGE_ERROR_INVALID_ARGUMENT 0x80001001
#define SCE_REMOTE_STORAGE_ERROR_FAILED_TO_CREATE_THREAD 0x80001002
#define SCE_REMOTE_STORAGE_ERROR_NOT_INITIALISED 0x80001003
#define SCE_REMOTE_STORAGE_ERROR_FAILED_TO_OPEN_WEB_BROWSER 0x80001004
#define SCE_REMOTE_STORAGE_ERROR_PSN_ACCOUNT_NOT_LINKED 0x80001005
#define SCE_REMOTE_STORAGE_ERROR_COULD_NOT_CREATE_SESSION 0x80001006
#define SCE_REMOTE_STORAGE_ERROR_FAILED_TO_ALLOCATE 0x80001007
#define SCE_REMOTE_STORAGE_ERROR_SESSION_DOES_NOT_EXIST 0x80001008
#define SCE_REMOTE_STORAGE_ERROR_REQ_ID_NOT_FOUND 0x80001009
#define SCE_REMOTE_STORAGE_ERROR_MAX_NUMBER_FILES_REACHED 0x8000100A
#define SCE_REMOTE_STORAGE_ERROR_NO_MORE_SYNCS 0x8000100B
#define SCE_REMOTE_STORAGE_ERROR_ALREADY_INITIALISED 0x8000100C
#define SCE_REMOTE_STORAGE_ERROR_INVALID_UPLOADID 0x8000100D
#define SCE_REMOTE_STORAGE_ERROR_FAILED_TO_OPEN_FILE 0x8000100E
#define SCE_REMOTE_STORAGE_ERROR_CLOUD_DATA_CORRUPTED 0x8000100F
#define SCE_REMOTE_STORAGE_ERROR_INVALID_CHAR_IN_FILE_NAME 0x80001010
#define SCE_REMOTE_STORAGE_ERROR_INVALID_JSON_RESPONSE 0x80001011
#define SCE_REMOTE_STORAGE_ERROR_REQUEST_ABORTED 0x80001012
#define SCE_REMOTE_STORAGE_ERROR_SERVER_ERROR 0x80002000 // Server errors can be between 0x80002064 to 0x800022BB both included
typedef enum SceRemoteStorageDataVisibility
{
PRIVATE = 0, // Only data owner can read and write data
PUBLIC_READ_ONLY, // Everyone can read this data. Owner can write to it
PUBLIC_READ_WRITE // Everyone can read and write data
} SceRemoteStorageDataVisibility;
typedef enum SceRemoteStorageEvent
{
USER_ACCOUNT_LINKED = 0, // User's account has been linked with PSN
PSN_SIGN_IN_REQUIRED, // User's PSN sign-in through web browser is required
WEB_BROWSER_RESULT, // Result of sceRemoteStorageOpenWebBrowser(). Please check retCode
GET_DATA_RESULT, // Result of sceRemoteStorageGetData(). Please check retCode
GET_DATA_PROGRESS, // Progress of sceRemoteStorageGetData() completion as a percentage. Please check retCode
SET_DATA_RESULT, // Result of sceRemoteStorageSetData(). Please check retCode
SET_DATA_PROGRESS, // Progress of sceRemoteStorageSetData() completion as a percentage. Please check retCode
GET_STATUS_RESULT, // Result of sceRemoteStorageGetStatus(). Please check retCode
ERROR_OCCURRED // A generic error has occurred. Please check retCode
} SceRemoteStorageEvent;
typedef enum SceRemoteStorageEnvironment
{
DEVELOPMENT = 0,
PRODUCTION
}SceRemoteStorageEnvironment;
typedef void (*sceRemoteStorageCallback)(const SceRemoteStorageEvent event, int32_t retCode, void * userData);
typedef struct SceRemoteStorageInitParamsThread
{
int32_t threadAffinity; // Thread affinity
int32_t threadPriority; // Priority that the thread runs out
} SceRemoteStorageInitParamsThread;
typedef struct SceRemoteStorageInitParamsPool
{
void * memPoolBuffer; // Memory pool used by sceRemoteStorage library
size_t memPoolSize; // Size of memPoolBuffer
} SceRemoteStorageInitParamsPool;
typedef struct SceRemoteStorageInitTimeout
{
uint32_t resolveMs; //Timeout for DNS resolution in milliseconds. Defaults to 30 seconds
uint32_t connectMs; //Timeout for first connection between client and server. Defaults to 30 seconds
uint32_t sendMs; //Timeout to send request to server. Defaults to 120 seconds
uint32_t receiveMs; //Timeout to receive information from server. Defaults to 120 seconds
SceRemoteStorageInitTimeout() : resolveMs(30 * 1000), connectMs(30 * 1000), sendMs(120 * 1000), receiveMs(120 * 1000) {}
}SceRemoteStorageInitTimeout;
typedef struct SceRemoteStorageInitParams
{
sceRemoteStorageCallback callback; // Event callback
void * userData; // Application defined data for callback
int32_t httpContextId; // PS4 only: Http context ID that was returned from sceHttpInit()
int32_t userId; // PS4 only: Current user, see SceUserServiceUserId
void * psnTicket; // PS3 only: The PSN ticket used to authenticate the user
size_t psnTicketSize; // PS3 only: The size of the PSN ticket in bytes
char clientId[SCE_REMOTE_STORAGE_CLIENT_ID_MAX_LEN]; // This represents your application on PSN, used to sign PSN user in for your title
SceRemoteStorageInitTimeout timeout; // Timeout for network transactions
SceRemoteStorageInitParamsPool pool; // Memory pool parameters
SceRemoteStorageInitParamsThread thread; // Thread creation parameters
SceRemoteStorageEnvironment environment; // Only used on non-PlayStation platforms: PSN Environment used by the library
} SceRemoteStorageInitParams;
typedef struct SceRemoteStorageGetDataReqParams
{
char fileName[SCE_REMOTE_STORAGE_DATA_NAME_MAX_LEN]; // Name of file on remote storage server
char pathLocation[SCE_REMOTE_STORAGE_DATA_LOCATION_MAX_LEN]; // File location on the HDD
char secureFileId[SCE_REMOTE_STORAGE_PS3_SAVEDATA_SECUREFILEID_SIZE]; // PS3 only. ID used for save data encryption
char ps3DataFilename[SCE_REMOTE_STORAGE_PS3_SAVEDATA_FILENAME_SIZE]; // PS3 only. Name of data file in save data
uint32_t ps3FileType; // PS3 only. Type of file, CELL_SAVEDATA_FILETYPE_XXX
SceAppUtilSaveDataDataSlot psVitaSaveDataSlot; // PS Vita only. Save data slot information
} SceRemoteStorageGetDataReqParams;
typedef struct SceRemoteStorageSetDataReqParams
{
char fileName[SCE_REMOTE_STORAGE_DATA_NAME_MAX_LEN]; // Name of file on remote storage server
char fileDescription[SCE_REMOTE_STORAGE_DATA_DESCRIPTION_MAX_LEN]; // Description of file on remote storage server
char pathLocation[SCE_REMOTE_STORAGE_DATA_LOCATION_MAX_LEN]; // File location on the HDD
char secureFileId[SCE_REMOTE_STORAGE_PS3_SAVEDATA_SECUREFILEID_SIZE]; // PS3 only. ID used for save data encryption
char ps3DataFilename[SCE_REMOTE_STORAGE_PS3_SAVEDATA_FILENAME_SIZE]; // PS3 only. Name of data file in save data
uint32_t ps3FileType; // PS3 only. Type of file, CELL_SAVEDATA_FILETYPE_XXX
SceRemoteStorageDataVisibility visibility; // Visibility of data
} SceRemoteStorageSetDataReqParams;
typedef struct SceRemoteStorageData
{
char fileName[SCE_REMOTE_STORAGE_DATA_NAME_MAX_LEN]; // Name of file on remote storage server
char fileDescription[SCE_REMOTE_STORAGE_DATA_DESCRIPTION_MAX_LEN]; // Description of file on remote storage server
size_t fileSize; // Size of file in bytes
char md5Checksum[SCE_REMOTE_STORAGE_MD5_STRING_LENGTH]; // File MD5 checksum
char timeStamp[SCE_REMOTE_STORAGE_RFC2822_LENGTH]; // Time that data was written on the server. Format is RFC2822
SceRemoteStorageDataVisibility visibility; // Visibility of data
} SceRemoteStorageData;
typedef struct SceRemoteStorageWebBrowserReqParams { } SceRemoteStorageWebBrowseReqParams;
typedef struct SceRemoteStorageStatusReqParams { } SceRemoteStorageStatusReqParams;
typedef struct SceRemoteStorageAbortReqParams
{
uint32_t requestId; // The request Id to be aborted
} SceRemoteStorageAbortReqParams;
typedef struct SceRemoteStorageStatus
{
uint32_t numFiles; // Number of files user has on remote storage server
SceRemoteStorageData data[SCE_REMOTE_STORAGE_MAX_FILES]; // Details about data if available. Data buffer will not be retrieved
uint64_t remainingSyncs; // Remaining syncs. the user has for upload/download
} SceRemoteStorageStatus;
#endif